<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>ZNHOO</title>
 <link href="https://www.zhstar.win/atom.xml" rel="self"/>
 <link href="https://www.zhstar.win/"/>
 <updated>2026-03-03T14:05:58+00:00</updated>
 <id>https://www.zhstar.win</id>
 <author>
   <name>ZNHOO</name>
   <email>youwu@inventati.org</email>
 </author>

 
 <entry>
   <title>Migrate Docker Desktop to colima</title>
   <link href="/2024/12/27/colima/"/>
   <updated>2024-12-27T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2024/12/27/colima</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot; id=&quot;markdown-toc-introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#uninstall-docker-desktop&quot; id=&quot;markdown-toc-uninstall-docker-desktop&quot;&gt;Uninstall Docker Desktop&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#colima-setup&quot; id=&quot;markdown-toc-colima-setup&quot;&gt;colima Setup&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#install-colima&quot; id=&quot;markdown-toc-install-colima&quot;&gt;Install colima&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#colima-profile&quot; id=&quot;markdown-toc-colima-profile&quot;&gt;colima profile&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#config-colima&quot; id=&quot;markdown-toc-config-colima&quot;&gt;Config colima&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-colima&quot; id=&quot;markdown-toc-start-colima&quot;&gt;Start colima&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ssh-colima&quot; id=&quot;markdown-toc-ssh-colima&quot;&gt;ssh colima&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#inspect-colima&quot; id=&quot;markdown-toc-inspect-colima&quot;&gt;Inspect colima&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#update-colima&quot; id=&quot;markdown-toc-update-colima&quot;&gt;Update colima&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#clean-colima&quot; id=&quot;markdown-toc-clean-colima&quot;&gt;Clean colima&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#docker-cli-setup&quot; id=&quot;markdown-toc-docker-cli-setup&quot;&gt;Docker CLI Setup&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#install-docker-cli&quot; id=&quot;markdown-toc-install-docker-cli&quot;&gt;Install Docker CLI&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#config-docker-cli&quot; id=&quot;markdown-toc-config-docker-cli&quot;&gt;Config Docker CLI&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#switch-docker-engine&quot; id=&quot;markdown-toc-switch-docker-engine&quot;&gt;Switch Docker Engine&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#verify-docker-setup&quot; id=&quot;markdown-toc-verify-docker-setup&quot;&gt;Verify Docker Setup&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#unix-socket-file&quot; id=&quot;markdown-toc-unix-socket-file&quot;&gt;Unix Socket File&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#multi-platform-build&quot; id=&quot;markdown-toc-multi-platform-build&quot;&gt;Multi-platform Build&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ssh-agent-forwarding&quot; id=&quot;markdown-toc-ssh-agent-forwarding&quot;&gt;SSH Agent Forwarding&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mount-volumes&quot; id=&quot;markdown-toc-mount-volumes&quot;&gt;Mount Volumes&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#kubernetes-setup&quot; id=&quot;markdown-toc-kubernetes-setup&quot;&gt;Kubernetes Setup&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#enable-kubernetes&quot; id=&quot;markdown-toc-enable-kubernetes&quot;&gt;Enable Kubernetes&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#install-kubectl&quot; id=&quot;markdown-toc-install-kubectl&quot;&gt;Install kubectl&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#config-kubectl&quot; id=&quot;markdown-toc-config-kubectl&quot;&gt;Config kubectl&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#inspect-kubernetes&quot; id=&quot;markdown-toc-inspect-kubernetes&quot;&gt;Inspect Kubernetes&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#extreme-caution&quot; id=&quot;markdown-toc-extreme-caution&quot;&gt;EXTREME CAUTION&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#references&quot; id=&quot;markdown-toc-references&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As required by the company, we have to remove Docker Desktop from our macOS due to the pricing model change. After searching over the web, I found the &lt;a href=&quot;https://github.com/abiosoft/colima&quot;&gt;colima - container runtime&lt;/a&gt; a good alternative.&lt;/p&gt;

&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;CoLiMa&lt;/em&gt; stands for Containers on &lt;a href=&quot;https://github.com/lima-vm/lima&quot;&gt;Lima (Linux Virtual Machine)&lt;/a&gt;. It supports &lt;a href=&quot;https://github.com/abiosoft/colima?tab=readme-ov-file#features&quot;&gt;three container runtimes&lt;/a&gt;, namely &lt;a href=&quot;/2018/04/21/docker-newbie#docker-engine&quot;&gt;official Docker&lt;/a&gt; (default), &lt;a href=&quot;https://containerd.io/&quot;&gt;pure containerd&lt;/a&gt;, &lt;a href=&quot;https://linuxcontainers.org/incus&quot;&gt;Incus&lt;/a&gt;. In this post, we elect the default runtime.&lt;/p&gt;

&lt;p&gt;To &lt;a href=&quot;https://github.com/abiosoft/colima/blob/main/docs/FAQ.md&quot;&gt;put it simple&lt;/a&gt;, colima &lt;a href=&quot;/2018/04/21/docker-newbie/#docker-desktop&quot;&gt;creates a Linux Virtual Machine on macOS&lt;/a&gt; based on &lt;a href=&quot;https://developer.apple.com/documentation/hypervisor&quot;&gt;Hypervisor&lt;/a&gt; and Lima, and then spanws the specified runtime process within.&lt;/p&gt;

&lt;p&gt;Containers communicate with the VM instead of macOS host. To make resources on the macOS available to containers, please mount them to the VM first. See the &lt;a href=&quot;#ssh-agent-forwarding&quot;&gt;SSH Agent Forwarding&lt;/a&gt; example.&lt;/p&gt;

&lt;h1 id=&quot;uninstall-docker-desktop&quot;&gt;Uninstall Docker Desktop&lt;/h1&gt;

&lt;p&gt;Docker Desktop includes both the Docker CLI and Docker engine. After uninstallation, both components are removed, including images, containers, volumes, networks, etc.&lt;/p&gt;

&lt;p&gt;Once completed, all Docker objects are gone, inlcuding containers! See &lt;a href=&quot;https://docs.docker.com/desktop/uninstall/&quot;&gt;https://docs.docker.com/desktop/uninstall/&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;colima-setup&quot;&gt;colima Setup&lt;/h1&gt;

&lt;h2 id=&quot;install-colima&quot;&gt;Install colima&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;colima
...

&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; Installing dependencies &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;colima: lima
&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; Installing colima dependency: lima
&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; Downloading https://ghcr.io/v2/homebrew/core/lima/manifests/1.0.3
Already downloaded: /Users/jim/Library/Caches/Homebrew/downloads/1433d7017c4773c2360cdd9ae90a6bf68d86b93c83daac1ed445db685427e583--lima-1.0.3.bottle_manifest.json
&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; Pouring lima--1.0.3.arm64_sonoma.bottle.tar.gz
🍺  /opt/homebrew/Cellar/lima/1.0.3: 107 files, 205.6MB
&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; Installing colima
&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; Pouring colima--0.8.1.arm64_sonoma.bottle.tar.gz
&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; Caveats
Bash completion has been installed to:
  /opt/homebrew/etc/bash_completion.d

To start colima now and restart at login:
  brew services start colima
Or, &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;you don&lt;span class=&quot;s1&quot;&gt;&apos;t want/need a background service you can just run:
  /opt/homebrew/opt/colima/bin/colima start -f
==&amp;gt; Summary
🍺  /opt/homebrew/Cellar/colima/0.8.1: 11 files, 5.7MB
==&amp;gt; Running `brew cleanup colima`...

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

&lt;p&gt;Check version.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ colima version
colima version 0.8.1
git commit: 96598cc5b64e5e9e1e64891642b91edc8ac49d16

runtime: docker
&lt;span class=&quot;nb&quot;&gt;arch&lt;/span&gt;: aarch64
client: v27.4.1
server: v27.4.0

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;limactl &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
limactl version 1.0.3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lima is a dependency of the colima, and hence it is also installed.&lt;/p&gt;

&lt;h2 id=&quot;colima-profile&quot;&gt;colima profile&lt;/h2&gt;

&lt;p&gt;colima has an important concept of &lt;em&gt;profile&lt;/em&gt;. Each profile represents the configuration arguments (e.g. CPU architecture) of the Linux virtual machine, namely a colima &lt;em&gt;instance&lt;/em&gt;. The colima CLI has a global option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--profile, -p&lt;/code&gt; that defines the default configuration of colima engines by &lt;a href=&quot;#config-colima&quot;&gt;colima template&lt;/a&gt;. For example, we can create two profiles for CPU architectures &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aarch64&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x86_64&lt;/code&gt; respectively. The default profile name is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt; which uses the same CPU architecture as the macOS host.&lt;/p&gt;

&lt;p&gt;In this post, the terms &lt;em&gt;colima profile&lt;/em&gt;, &lt;em&gt;colima instance&lt;/em&gt;, &lt;em&gt;colima VM&lt;/em&gt; and &lt;em&gt;colima engine&lt;/em&gt; could be used interchangeably.&lt;/p&gt;

&lt;p&gt;For the list of supported configuration fields, please refer to the &lt;a href=&quot;#config-colima&quot;&gt;config colima&lt;/a&gt; section.&lt;/p&gt;

&lt;h3 id=&quot;config-colima&quot;&gt;Config colima&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$COLIMA_HOME&lt;/code&gt; environment variable specifies the directory that holds everything of colima. By default, it points to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.colima&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;21:52:17 jim@Jims-MacBook-Pro ~
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export COLIMA_HOME=$HOME/.colima&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; .bashrc

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COLIMA_HOME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.colima
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$COLIMA_HOME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The list of supported configurations can be found by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colima help start&lt;/code&gt;. They can be resources (CPU/memory) constraints, CPU architectures, engines (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--runtime&lt;/code&gt;), dns, etc. We can even forward environment variables on the host to the VM via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To set the default config of a &lt;a href=&quot;#colima-profile&quot;&gt;profile&lt;/a&gt;, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colima template -p &amp;lt;profile&amp;gt;&lt;/code&gt;. The config file of a profile is located at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${COLIMA_HOME}/_templates/&amp;lt;profile&amp;gt;.yaml&lt;/code&gt;. Each CLI option has a corresponding field in this file with detailed explanation. Actually, the configuration of colima is transformed to &lt;a href=&quot;#inspect-colima&quot;&gt;configurations of lima VM and Docker components&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima template &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--editor&lt;/span&gt; nano

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ggrep &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^[[:space:]]*[-a-z]+&apos;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$COLIMA_HOME&lt;/span&gt;/_templates/default.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can fetch a config template at &lt;a href=&quot;https://gist.github.com/outsinre/b7c8347ff0c0b0053044a9c1b61f4b6e&quot;&gt;https://gist.github.com/outsinre/b7c8347ff0c0b0053044a9c1b61f4b6e&lt;/a&gt;. The default resources assigned to the Linux VM is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt; CPUs, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt; GiB memory and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100&lt;/code&gt; GiB disk space. We want to increase the CPU and memory a bit. Specially, we can set as many CPU (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8&lt;/code&gt; out &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10&lt;/code&gt;) as we can, as the OS is smart enough to schedual the CPU between the colima VM and the system. By default, this rule applies to memory as well (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;30&lt;/code&gt; out &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;36&lt;/code&gt;). We call this as &lt;em&gt;ballooning&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, we want to update more fields. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmType&lt;/code&gt; is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vz&lt;/code&gt;instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qemu&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mountType&lt;/code&gt; is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virtiofs&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rosetta&lt;/code&gt; is turned on. The three configs can boost performance on Apple M1 chip. Optionally, we can enable &lt;a href=&quot;#kubernetes-cli-setup&quot;&gt;Kubernetes support&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, &lt;a href=&quot;https://github.com/lima-vm/lima/issues/2789&quot;&gt;due to a macOS bug&lt;/a&gt;, the memory ballooning does not work with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmType: vz&lt;/code&gt;. If the macOS experiences performance issue, reduce the memory size or restart colima.&lt;/p&gt;

&lt;p&gt;If you experience any network issue, like cannot connecting to public Internet from within containers, cannot pulling images, cannot access to HTTPS URLs, please enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--network-address&lt;/code&gt; and/or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--network-preferred-route=false&lt;/code&gt;. Once enabled, the VM has an reachable IP address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.64.8&lt;/code&gt;. See &lt;a href=&quot;https://github.com/abiosoft/colima/blob/main/docs/FAQ.md#the-virtual-machines-ip-is-not-reachable&quot;&gt;The Virtual Machine&apos;s IP is not reachable&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima list
PROFILE    STATUS     ARCH       CPUS    MEMORY    DISK      RUNTIME    ADDRESS
default    Running    aarch64    8       30GiB     100GiB    docker     192.168.64.8

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl http://192.168.64.8:32771/anything
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl http://localhost:32771/anything
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Upon &lt;a href=&quot;#start-colima&quot;&gt;colima start&lt;/a&gt;, we can customize the default config in three ways.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;With the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--edit&lt;/code&gt; CLI option&lt;/li&gt;
  &lt;li&gt;With the specific config CLI option (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dns&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Manually edit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${COLIMA_HOME}/&amp;lt;profile&amp;gt;/&amp;lt;hostname&amp;gt;.yaml&lt;/code&gt;. For example, the hostname of the colima VM of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt; profile is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colima&lt;/code&gt;. It can be customized with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hostname&lt;/code&gt; field.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reference &lt;a href=&quot;https://github.com/abiosoft/colima/blob/main/docs/FAQ.md#can-config-file-be-used-instead-of-cli-flags&quot;&gt;Can config file be used instead of cli flags?&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;start-colima&quot;&gt;Start colima&lt;/h2&gt;

&lt;p&gt;List existing instances.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima list
WARN[0000] No instance found. Run &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;colima start&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; to create an instance.
PROFILE    STATUS    ARCH    CPUS    MEMORY    DISK    RUNTIME    ADDRESS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/abiosoft/colima?tab=readme-ov-file#usage&quot;&gt;Start an instance&lt;/a&gt; of the &lt;em&gt;default&lt;/em&gt; profile.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima start &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--template&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--kubernetes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true
&lt;/span&gt;INFO[0000] starting colima
INFO[0000] runtime: docker+k3s
INFO[0001] starting ...                                  &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;vm
INFO[0013] provisioning ...                              &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;docker
INFO[0014] starting ...                                  &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;docker
INFO[0015] provisioning ...                              &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kubernetes
INFO[0015] downloading and installing ...                &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kubernetes
INFO[0109] loading oci images ...                        &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kubernetes
INFO[0118] starting ...                                  &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kubernetes
INFO[0122] updating config ...                           &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kubernetes
INFO[0123] Switched to context &lt;span class=&quot;s2&quot;&gt;&quot;colima&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kubernetes
INFO[0124] &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The colima instance exposes a &lt;a href=&quot;#unix-socket-file&quot;&gt;Docker Unix socket file docker.sock&lt;/a&gt; to the macOS host.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima list
PROFILE    STATUS     ARCH       CPUS    MEMORY    DISK      RUNTIME    ADDRESS
default    Running    aarch64    4       8GiB      100GiB    docker

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima status &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default
INFO[0000] colima is running using macOS Virtualization.Framework
INFO[0000] &lt;span class=&quot;nb&quot;&gt;arch&lt;/span&gt;: aarch64
INFO[0000] runtime: docker
INFO[0000] mountType: sshfs
INFO[0000] socket: unix:///Users/jim/.colima/default/docker.sock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A new &lt;a href=&quot;#switch-docker-engine&quot;&gt;Docker context&lt;/a&gt; called &lt;em&gt;colima&lt;/em&gt; is created and &lt;a href=&quot;#config-colima&quot;&gt;automatically activated (autoActivate)&lt;/a&gt;. The associated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker.sock&lt;/code&gt; is &lt;a href=&quot;#unit-socket-file&quot;&gt;mapped from the colima VM to the macOS host&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker context list
NAME       DESCRIPTION                               DOCKER ENDPOINT                                     ERROR
colima &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;   colima                                    unix:///Users/jim/.colima/default/docker.sock
default    Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The original Docker official context called &lt;em&gt;default&lt;/em&gt; is still bound to the &lt;a href=&quot;#unix-socket-file&quot;&gt;DOCKER_HOST environment variable&lt;/a&gt;. We can use this variable to &lt;a href=&quot;#unix-socket-file&quot;&gt;switch between different engines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A new &lt;a href=&quot;#switch-docker-engine&quot;&gt;Docker builder&lt;/a&gt; &lt;em&gt;colima&lt;/em&gt; is created and automatically activated. Regarding the &lt;em&gt;error&lt;/em&gt; status of the Docker official &lt;em&gt;default&lt;/em&gt; builder, see &lt;a href=&quot;#unix-socket-file&quot;&gt;Unix socket file&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker buildx &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;NAME/NODE    DRIVER/ENDPOINT   STATUS    BUILDKIT   PLATFORMS
colima&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;      docker
 &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; colima    &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; colima        running   v0.17.3    linux/amd64 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;+2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, linux/arm64, linux/386
default                        error

Cannot load builder default: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can also make use of &lt;em&gt;brew services&lt;/em&gt; to start colima. But currently, it does not support CLI options. What is worse, it &lt;a href=&quot;https://github.com/abiosoft/colima/issues/1234&quot;&gt;can not create the docker context&lt;/a&gt;! The advantage of &lt;em&gt;brew services start&lt;/em&gt; is it would regiester the service and autostart at system booting.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# take around 30s&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew services start colima

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew services info colima
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;ssh-colima&quot;&gt;ssh colima&lt;/h2&gt;

&lt;p&gt;A SSH config entry is inserted to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${COLIMA_HOME}/ssh_config&lt;/code&gt; for the colima VM. Additionally, this entry is also inserted to the macOS SSH config.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;less &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COLIMA_HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/ssh_config

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; ~/.ssh/config
Include /Users/jim/.colima/ssh_config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, we can get into the VM via &lt;em&gt;ssh&lt;/em&gt;. Please check the &lt;a href=&quot;#config-colima&quot;&gt;config file&lt;/a&gt; for the &lt;em&gt;hostname&lt;/em&gt; field.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh &amp;lt;&lt;span class=&quot;nb&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COLIMA_HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/ssh_config &amp;lt;&lt;span class=&quot;nb&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, colima provides the &lt;em&gt;ssh&lt;/em&gt; sub-command accepting the profile name. This sub-command preserves the local dir.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;21:37:28 jim@Jims-MacBook-Pro ~/misc
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima ssh &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--very-verbose&lt;/span&gt;
TRAC[0000] cmd &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;limactl&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;list&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;colima&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--json&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
TRAC[0000] cmd int &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;limactl&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;shell&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--workdir&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/Users/jim/misc&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;colima&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;inspect-colima&quot;&gt;Inspect colima&lt;/h2&gt;

&lt;p&gt;After getting into the VM, we find many facts.&lt;/p&gt;

&lt;p&gt;The VM OS is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ubuntu 24.04&lt;/code&gt;. Please check the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diskImage&lt;/code&gt; filed in the &lt;a href=&quot;#config-colima&quot;&gt;config file&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh colima
Last login: Tue Dec 31 11:54:26 2024 from 192.168.5.2

jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;
Linux colima 6.8.0-50-generic &lt;span class=&quot;c&quot;&gt;#51-Ubuntu SMP PREEMPT_DYNAMIC Sat Nov  9 18:03:35 UTC 2024 aarch64 aarch64 aarch64 GNU/Linux&lt;/span&gt;

jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/os-release
&lt;span class=&quot;nv&quot;&gt;PRETTY_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ubuntu 24.04.1 LTS&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ubuntu&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;VERSION_ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;24.04&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;24.04.1 LTS (Noble Numbat)&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;VERSION_CODENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;noble
&lt;span class=&quot;nv&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ubuntu
&lt;span class=&quot;nv&quot;&gt;ID_LIKE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;debian
&lt;span class=&quot;nv&quot;&gt;HOME_URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://www.ubuntu.com/&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;SUPPORT_URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://help.ubuntu.com/&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;BUG_REPORT_URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://bugs.launchpad.net/ubuntu/&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PRIVACY_POLICY_URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://www.ubuntu.com/legal/terms-and-policies/privacy-policy&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;UBUNTU_CODENAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;noble
&lt;span class=&quot;nv&quot;&gt;LOGO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ubuntu-logo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The colima VM is assigned two IP addresses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.5.1&lt;/code&gt; and &lt;a href=&quot;#config-colima&quot;&gt;192.168.64.8&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ip addr
2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000
    &lt;span class=&quot;nb&quot;&gt;link&lt;/span&gt;/ether 52:55:55:f2:6b:1d brd ff:ff:ff:ff:ff:ff
    inet 192.168.5.1/24 metric 200 brd 192.168.5.255 scope global dynamic eth0
       valid_lft 3596sec preferred_lft 3596sec
    inet6 fe80::5055:55ff:fef2:6b1d/64 scope &lt;span class=&quot;nb&quot;&gt;link
       &lt;/span&gt;valid_lft forever preferred_lft forever
3: col0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000
    &lt;span class=&quot;nb&quot;&gt;link&lt;/span&gt;/ether 52:55:55:c5:da:42 brd ff:ff:ff:ff:ff:ff
    inet 192.168.64.8/24 metric 300 brd 192.168.64.255 scope global dynamic col0
       valid_lft 1796sec preferred_lft 1796sec
    inet6 fd1e:d47e:8ea5:3cab:5055:55ff:fec5:da42/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591899sec preferred_lft 604699sec
    inet6 fe80::5055:55ff:fec5:da42/64 scope &lt;span class=&quot;nb&quot;&gt;link
       &lt;/span&gt;valid_lft forever preferred_lft forever

jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ip route
default via 192.168.5.2 dev eth0 proto dhcp src 192.168.5.1 metric 200
default via 192.168.64.1 dev col0 proto dhcp src 192.168.64.8 metric 300
172.17.0.0/16 dev docker0 proto kernel scope &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;src 172.17.0.1 linkdown
172.26.0.0/16 dev br-063f6ac19dfc proto kernel scope &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;src 172.26.0.1
192.168.5.0/24 dev eth0 proto kernel scope &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;src 192.168.5.1 metric 200
192.168.5.2 dev eth0 proto dhcp scope &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;src 192.168.5.1 metric 200
192.168.64.0/24 dev col0 proto kernel scope &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;src 192.168.64.8 metric 300
192.168.64.1 dev col0 proto dhcp scope &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;src 192.168.64.8 metric 300
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There is a hidden IP address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.5.2&lt;/code&gt; which is actually DNS server both on the macOS host and in the colima VM.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jimgray@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eF&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--forest&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;d]ns
dnsmasq     1277       1  0  3158  2324   0 21:09 ?        00:00:00 /usr/sbin/dnsmasq &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; /run/dnsmasq/dnsmasq.pid &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; dnsmasq &lt;span class=&quot;nt&quot;&gt;-7&lt;/span&gt; /etc/dnsmasq.d

jimgray@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/dnsmasq.d/01-colima.conf
&lt;span class=&quot;c&quot;&gt;# Generated by Colima&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Do not edit this file manually&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/host.docker.internal/192.168.5.2
&lt;span class=&quot;nv&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/host.lima.internal/192.168.5.2
&lt;span class=&quot;nv&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/colima.internal/192.168.5.1
&lt;span class=&quot;nv&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/colima/127.0.0.1

&lt;span class=&quot;nv&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;192.168.5.2

&lt;span class=&quot;nv&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;eth0
listen-address&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;192.168.5.1
bind-interfaces

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;lsof &lt;span class=&quot;nt&quot;&gt;-nPR&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; tcp:53
COMMAND   PID PPID           USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
mDNSRespo 674    1 _mdnsresponder   31u  IPv4 0xd2ba4c44ed2bcfcc      0t0  TCP &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;:53 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;LISTEN&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
mDNSRespo 674    1 _mdnsresponder   33u  IPv6 0xd8ba243fde3bf9d9      0t0  TCP &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;:53 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;LISTEN&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/resolv.conf
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# macOS Notice&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# This file is not consulted for DNS hostname resolution, address&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# resolution, or the DNS query routing mechanism used by most&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# processes on this system.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# To view the DNS configuration used by this system, use:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   scutil --dns&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# SEE ALSO&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   dns-sd(1), scutil(8)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# This file is automatically generated.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
nameserver 192.168.5.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can access to the SSH port of the colima VM.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; | ncat &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; 192.168.64.8 22
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; | ncat &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; 192.168.5.2 22
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The same user account as the macOS host is created. Attention please; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uid&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gid&lt;/code&gt; numbers are different.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;
/home/jim.linux

jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;uid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;501&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;jim&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;gid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;jim&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;groups&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1000&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;jim&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;,991&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;docker&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt; /etc/passwd
jim:x:501:1000:Jim Zhan Hu:/home/jim.linux:/bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href=&quot;/2018/04/21/docker-newbie/#architecture&quot;&gt;dockerd, containerd, containerd-shim and runc&lt;/a&gt; all reside within the VM.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eF&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--forest&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;c]ontainerd
root         446       1  0 465190 40872  1 13:58 ?        00:00:11 /usr/bin/containerd
root        1218       1  0 546591 71184  2 13:58 ?        00:00:03 /usr/bin/dockerd &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; fd:// &lt;span class=&quot;nt&quot;&gt;--containerd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/run/containerd/containerd.sock &lt;span class=&quot;nt&quot;&gt;--host-gateway-ip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;192.168.5.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We check the logs of colima.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# logs of daemons in the VM&lt;/span&gt;
jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;journalctl &lt;span class=&quot;nt&quot;&gt;-xfe&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; docker
jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;journalctl &lt;span class=&quot;nt&quot;&gt;-xfe&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; containerd

&lt;span class=&quot;c&quot;&gt;# logs of colima&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$COLIMA_HOME&lt;/span&gt;/_lima/colima/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.log
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt;  1 jim  staff  12184 Jan  6 20:30 /Users/jim/.colima/_lima/colima/ha.stderr.log
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt;  1 jim  staff    167 Jan  6 20:28 /Users/jim/.colima/_lima/colima/ha.stdout.log
&lt;span class=&quot;nt&quot;&gt;-rw-------&lt;/span&gt;  1 jim  staff     51 Jan  6 20:28 /Users/jim/.colima/_lima/colima/serialv.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Data of the colima Engine is stored under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${COLIMA_HOME}/_lima/&amp;lt;hostname&amp;gt;&lt;/code&gt;. There are multiple meaningful files &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colima.yaml&lt;/code&gt; (configuration of colima), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lima.yaml&lt;/code&gt; (configuration of lima) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cloud-config.yaml&lt;/code&gt; (user account). Whenever you encounter issues, please inspect these files.&lt;/p&gt;

&lt;h2 id=&quot;update-colima&quot;&gt;Update colima&lt;/h2&gt;

&lt;p&gt;When it comes to &quot;update colima&quot;, we mean updating either the whole colima or just the Docker runtime part.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;To update the Docker runtime part, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colima update -p &amp;lt;profile&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;To update the whole colima (Docker runtime included), refer to &lt;a href=&quot;#install-colima&quot;&gt;Install colima&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;clean-colima&quot;&gt;Clean colima&lt;/h2&gt;

&lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colima k8s stop&lt;/code&gt; and/or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colima stop&lt;/code&gt; to shutdown the colima instance.&lt;/p&gt;

&lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colima delete&lt;/code&gt; to destroy everything, including containers, images, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${COLIMA_HOME}/&amp;lt;profile&amp;gt;/&amp;lt;hostname&amp;gt;.yaml&lt;/code&gt; &lt;a href=&quot;#config-colima&quot;&gt;config&lt;/a&gt;, etc. It simulates a fresh installation.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima delete &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
are you sure you want to delete colima and all settings? &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;y/N]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v0.9.0&lt;/code&gt;, each container has a separate VM disk for data persistence. The VM disk persists accros &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;colima delete&lt;/code&gt;. To remove the VM disk as we pass the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--data&lt;/code&gt; option.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima delete &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;colima caches downloaded assets under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~$HOME/Library/Caches/{colima,lima}&lt;/code&gt;, we can further prune the cache.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima prune &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&apos;/Users/jim/Library/Caches/colima&apos;&lt;/span&gt; and &lt;span class=&quot;s1&quot;&gt;&apos;/Users/jim/Library/Caches/lima&apos;&lt;/span&gt; will be emptied, are you sure? &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;y/N] y
INFO[0001] Pruning &lt;span class=&quot;s2&quot;&gt;&quot;/Users/jim/Library/Caches/colima&quot;&lt;/span&gt;
INFO[0000] Pruning &lt;span class=&quot;s2&quot;&gt;&quot;/Users/jim/Library/Caches/lima&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;docker-cli-setup&quot;&gt;Docker CLI Setup&lt;/h1&gt;

&lt;h2 id=&quot;install-docker-cli&quot;&gt;Install Docker CLI&lt;/h2&gt;

&lt;p&gt;Install Docker CLI. Please do &lt;strong&gt;NOT&lt;/strong&gt; add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cask&lt;/code&gt; CLI option!&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Additionally, we install additional Docker plugins.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;docker-compose docker-buildx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;config-docker-cli&quot;&gt;Config Docker CLI&lt;/h2&gt;

&lt;p&gt;Firstly, let us set the configuration directory via the &lt;a href=&quot;https://docs.docker.com/reference/cli/docker/#environment-variables&quot;&gt;DOCKER_CONFIG&lt;/a&gt; environment variable.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;17:12:05 jim@Jims-MacBook-Pro ~
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export DOCKER_CONFIG=$HOME/.config/docker&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$DOCKER_CONFIG&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We configure the Docker CLI let it find the plugins, otherwise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker compose&lt;/code&gt; would report &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;compose&apos; is not a docker command&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;17:13:15 jim@Jims-MacBook-Pro ~
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; .config/docker/config.json
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;auths&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;cliPluginsExtraDirs&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;/opt/homebrew/lib/docker/cli-plugins&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;switch-docker-engine&quot;&gt;Switch Docker Engine&lt;/h2&gt;

&lt;p&gt;In the &lt;a href=&quot;#start-colima&quot;&gt;Start colima&lt;/a&gt; section, the &lt;a href=&quot;#/2018/04/21/docker-newbie/#docker-context&quot;&gt;Docker Context&lt;/a&gt; and the &lt;a href=&quot;#multi-platform-build&quot;&gt;Docker builder&lt;/a&gt; are automatically switched to the colima Engine. But to definitely let Dokcer CLI communicate with the colima Engine, we should explicitly switch to it.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker context &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker context use colima
colima
Current context is now &lt;span class=&quot;s2&quot;&gt;&quot;colima&quot;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;less &lt;span class=&quot;nv&quot;&gt;$DOCKER_CONFIG&lt;/span&gt;/contexts/meta/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/meta.json

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker buildx &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker buildx use colima 
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;less &lt;span class=&quot;nv&quot;&gt;$DOCKER_CONFIG&lt;/span&gt;/buildx/current
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is required if there are multiple engines available on the macOS host.&lt;/p&gt;

&lt;h2 id=&quot;verify-docker-setup&quot;&gt;Verify Docker Setup&lt;/h2&gt;

&lt;p&gt;Let us start with a simple apline container. From the output, an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aarch64&lt;/code&gt; container was created. So, we can say the colima VM is also &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aarch64&lt;/code&gt;. This matches the fact that the macOS is an Apple M1 chip.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ti&lt;/span&gt; alpine &lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;
Linux 12025f4e1ef2 6.8.0-50-generic &lt;span class=&quot;c&quot;&gt;#51-Ubuntu SMP PREEMPT_DYNAMIC Sat Nov  9 18:03:35 UTC 2024 aarch64 Linux&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is an example of a Docker Compose with 7 containers.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker compose &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;NAME                STATUS              CONFIG FILES
kong-dev            running&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;7&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;          /Users/jim/workspace/biji/archive/kong-dev-compose.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Correspondingly, within the colima engine, there should be 7 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;containerd-shim-runc&lt;/code&gt; processes.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima ssh &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default

jim@colima:/Users/jim&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eFH&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;r]unc
root       32809       1  0 309514 14604  3 13:51 ?        00:00:04   /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; a439998840a3dec6c05c77eba72a7fa2301093e6f166e04a94864a288f91e8cf &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
root       32886       1  0 309386 13768  3 13:51 ?        00:00:01   /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; 41227a00a3619d4409a9295112b0b2440227918c96d86809aca4580fe042c714 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
root       32925       1  0 309450 13880  1 13:51 ?        00:00:01   /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; a6770fbd56d55312abfa23b200e57c3c9bd8a7d38c96c95c62aed387882493ea &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
root       32953       1  0 309514 14640  3 13:51 ?        00:00:04   /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; 92346757d8056583cac160735a9c6e7b4b802ea161fd722242c3a33ee40b6b06 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
root       32961       1  0 309386 14520  0 13:51 ?        00:00:04   /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; dfee6297c63fac0ddf412dacc925cf4bd7e7508d0cff5be29fd822a9251a84b3 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
root       33117       1  0 309450 15132  1 13:51 ?        00:00:04   /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; 909fed36235360ec776dc52b796bd33cb77b42409200a1415ce9300dd90e9ed4 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
root       33691       1  0 309450 13760  2 13:51 ?        00:00:01   /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; 9a1ae83f551302204f7a2da0fd26ae538afb59e97ece44a0255e44e99ab20e95 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Addtionally, for each container, there are several &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-proxy&lt;/code&gt; processes spawned by &lt;a href=&quot;#inspect-colima&quot;&gt;dockerd&lt;/a&gt; when a container is publishing ports, accompanyed by some &lt;a href=&quot;/2015/01/29/iptables/&quot;&gt;iptables rules&lt;/a&gt; to forward traffic to or from the container within the colima engine.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima ssh &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default

jim@colima:/Users/jim&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eFH&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1]72.26.0.2
root       32538    1273  0 417873 3712   2 13:51 ?        00:00:00     /usr/bin/docker-proxy &lt;span class=&quot;nt&quot;&gt;-proto&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-host-ip&lt;/span&gt; 0.0.0.0 &lt;span class=&quot;nt&quot;&gt;-host-port&lt;/span&gt; 32768 &lt;span class=&quot;nt&quot;&gt;-container-ip&lt;/span&gt; 172.26.0.2 &lt;span class=&quot;nt&quot;&gt;-container-port&lt;/span&gt; 80
root       32567    1273  0 454705 3840   2 13:51 ?        00:00:00     /usr/bin/docker-proxy &lt;span class=&quot;nt&quot;&gt;-proto&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-host-ip&lt;/span&gt; :: &lt;span class=&quot;nt&quot;&gt;-host-port&lt;/span&gt; 32768 &lt;span class=&quot;nt&quot;&gt;-container-ip&lt;/span&gt; 172.26.0.2 &lt;span class=&quot;nt&quot;&gt;-container-port&lt;/span&gt; 80
root       32586    1273  0 436321 3840   1 13:51 ?        00:00:00     /usr/bin/docker-proxy &lt;span class=&quot;nt&quot;&gt;-proto&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-host-ip&lt;/span&gt; 0.0.0.0 &lt;span class=&quot;nt&quot;&gt;-host-port&lt;/span&gt; 32772 &lt;span class=&quot;nt&quot;&gt;-container-ip&lt;/span&gt; 172.26.0.2 &lt;span class=&quot;nt&quot;&gt;-container-port&lt;/span&gt; 443
root       32616    1273  0 436257 3712   3 13:51 ?        00:00:00     /usr/bin/docker-proxy &lt;span class=&quot;nt&quot;&gt;-proto&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-host-ip&lt;/span&gt; :: &lt;span class=&quot;nt&quot;&gt;-host-port&lt;/span&gt; 32772 &lt;span class=&quot;nt&quot;&gt;-container-ip&lt;/span&gt; 172.26.0.2 &lt;span class=&quot;nt&quot;&gt;-container-port&lt;/span&gt; 443

~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; nat &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; POSTROUTING &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; 172.26.0.2/32 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; 172.26.0.2/32 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 80 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; MASQUERADE
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; POSTROUTING &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; 172.26.0.2/32 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; 172.26.0.2/32 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 443 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; MASQUERADE
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; DOCKER &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; br-7034e9493ba4 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 32768 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; DNAT &lt;span class=&quot;nt&quot;&gt;--to-destination&lt;/span&gt; 172.26.0.2:80
&lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; DOCKER &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; br-7034e9493ba4 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;--dport&lt;/span&gt; 32772 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; DNAT &lt;span class=&quot;nt&quot;&gt;--to-destination&lt;/span&gt; 172.26.0.2:443
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, each published port requires a standalone &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-proxy&lt;/code&gt; process, &lt;a href=&quot;https://github.com/moby/moby/issues/47537&quot;&gt;consuming quite a lot of memory and CPU&lt;/a&gt;! Setting the field &lt;a href=&quot;https://docs.docker.com/reference/cli/dockerd/&quot;&gt;userland-proxy&lt;/a&gt; to &lt;em&gt;false&lt;/em&gt; can &lt;a href=&quot;https://github.com/docker/docs/issues/17312&quot;&gt;solve the performance issue&lt;/a&gt;. See section &lt;a href=&quot;#config-colima&quot;&gt;Config colima&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;unix-socket-file&quot;&gt;Unix Socket File&lt;/h2&gt;

&lt;p&gt;From the &lt;a href=&quot;#start-colima&quot;&gt;Start colima&lt;/a&gt; section and the &lt;a href=&quot;#inspect-colima&quot;&gt;Inspect colima&lt;/a&gt; section, we know the &lt;a href=&quot;/2018/04/21/docker-newbie/#dockersock&quot;&gt;Docker Unix socket docker.sock&lt;/a&gt; is mapped from the colima VM to the macOS host.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+---------------------------------------------------------------------------------------------------------------+
|                                                                                                               |
|                                                                                                               |
|    macOS Host                                                                                                 |
|                                                                                                               |
|                                                                                                               |
|        +-----------------------------------------------+                                                      |
|        |                                               |                                                      |
|        |   colima Engine                               |                                                      |
|        |                                               |                                                      |
|        |                                               |                                                      |
|        |     dockerd containerd containerd-shim runc   |                                                      |
|        |                                               |                                                      |
|        |                                               |                                                      |
|        |         unix:///var/run/docker.sock      -----+---&amp;gt; unix:///Users/jim/.colima/default/docker.sock    |
|        |                                               |                                                      |
|        +-----------------------------------------------+                                                      |
|                                                                                                               |
|                                                                                                               |
+---------------------------------------------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Actually, we can manage the containers directly within the colima VM.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh colima
Last login: Tue Jan 21 22:09:08 2025 from 192.168.5.2

jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker context &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;NAME        DESCRIPTION                               DOCKER ENDPOINT               ERROR
default &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;   Current DOCKER_HOST based configuration   unix:///var/run/docker.sock

jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker compose &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;NAME                STATUS              CONFIG FILES
kong-dev            running&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;7&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;          /Users/jim/workspace/biji/archive/kong-dev-compose.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, applications on the macOS host can not find the colima engine as they assume the default pathname &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unix:///var/run/docker.sock&lt;/code&gt;. We should configure the &lt;a href=&quot;https://docs.docker.com/reference/cli/docker/#environment-variables&quot;&gt;DOCKER_HOST Docker environment variable&lt;/a&gt; to the &lt;em&gt;colima engine&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Take VSCode for example, we can set the variable in the &lt;a href=&quot;https://code.visualstudio.com/remote/advancedcontainers/develop-remote-host#_connect-using-docker-contexts&quot;&gt;Docker extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/docker-host.png&quot; alt=&quot;docker-host.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For CLI applications, here is an example.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ DOCKER_HOST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;unix://&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COLIMA_HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/default/docker.sock&quot;&lt;/span&gt; docker context &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;NAME        DESCRIPTION                               DOCKER ENDPOINT                                     ERROR
colima      colima                                    unix:///Users/jim/.colima/default/docker.sock
default &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;   Current DOCKER_HOST based configuration   unix:///Users/jim/.colima/default/docker.sock
Warning: DOCKER_HOST environment variable overrides the active context. To use a context, either &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;the global &lt;span class=&quot;nt&quot;&gt;--context&lt;/span&gt; flag, or &lt;span class=&quot;nb&quot;&gt;unset &lt;/span&gt;DOCKER_HOST environment variable.

~ &lt;span class=&quot;nv&quot;&gt;$ DOCKER_HOST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;unix://&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COLIMA_HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/default/docker.sock&quot;&lt;/span&gt; docker buildx &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;NAME/NODE     DRIVER/ENDPOINT   STATUS    BUILDKIT   PLATFORMS
colima        docker
 &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; colima     &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; colima        running   v0.17.3    linux/amd64 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;+2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, linux/arm64, linux/386
default&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;      docker
 &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; default    &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; default       running   v0.17.3    linux/amd64 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;+2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, linux/arm64, linux/386
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;See &lt;a href=&quot;https://github.com/abiosoft/colima/blob/main/docs/FAQ.md#cannot-connect-to-the-docker-daemon-at-unixvarrundockersock-is-the-docker-daemon-running&quot;&gt;FAQ Cannot connect to the Docker daemon&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;multi-platform-build&quot;&gt;Multi-platform Build&lt;/h2&gt;

&lt;p&gt;The default &lt;a href=&quot;https://docs.docker.com/build/builders/drivers/&quot;&gt;docker build driver&lt;/a&gt; prioritizes simplicity but does not support advanced features like &lt;a href=&quot;https://docs.docker.com/build/building/multi-platform/&quot;&gt;multi-platform build&lt;/a&gt;, caching, etc.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker buildx &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;NAME/NODE    DRIVER/ENDPOINT   STATUS    BUILDKIT   PLATFORMS
colima&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;      docker
 &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; colima    &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; colima        running   v0.17.3    linux/amd64 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;+2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, linux/arm64, linux/386
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To support multi-platform build, create a builder with the &lt;a href=&quot;https://docs.docker.com/build/builders/drivers/&quot;&gt;docker-container build driver&lt;/a&gt; that has multi-platform support. This driver would create a dedicated container as the builder backend.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--use&lt;/code&gt; option would switch to the newly created builder, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--bootstrap&lt;/code&gt; would start the dedicated container in advanced.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker buildx create &lt;span class=&quot;nt&quot;&gt;--use&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--bootstrap&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; multi-platform-builder &lt;span class=&quot;nt&quot;&gt;--node&lt;/span&gt; multi-platform-builder &lt;span class=&quot;nt&quot;&gt;--driver&lt;/span&gt; docker-container &lt;span class=&quot;nt&quot;&gt;--platform&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;linux/arm64,linux/amd64&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;+] Building 4.4s &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1/1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; FINISHED
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;internal] booting buildkit                                                                                                                                                                                               4.4s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; pulling image moby/buildkit:buildx-stable-1                                                                                                                                                                            4.0s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; creating container buildx_buildkit_multi-platform-builder                                                                                                                                                              0.4s
multi-platform-builder

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker buildx &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;NAME/NODE                    DRIVER/ENDPOINT    STATUS    BUILDKIT   PLATFORMS
multi-platform-builder&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;      docker-container
 &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; multi-platform-builder    &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; colima         running   v0.18.2    linux/amd64&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;+2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, linux/arm64&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;, linux/386
colima                       docker
 &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; colima                    &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; colima         running   v0.17.3    linux/amd64 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;+2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, linux/arm64, linux/386

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker ps
CONTAINER ID   IMAGE                           COMMAND                  CREATED          STATUS          PORTS     NAMES
80b4fa8ad380   moby/buildkit:buildx-stable-1   &lt;span class=&quot;s2&quot;&gt;&quot;buildkitd --allow-i…&quot;&lt;/span&gt;   14 seconds ago   Up 14 seconds             buildx_buildkit_multi-platform-builder
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let&apos;s build a &quot;linux/amd64&quot; image on the &quot;linux/arm64&quot; machine.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A1&lt;/span&gt; platforms kong-dev-compose.yaml
72:      platforms:                    &lt;span class=&quot;c&quot;&gt;# Docker will determine the native platform unless you specify a different value.&lt;/span&gt;
73-      - &lt;span class=&quot;s2&quot;&gt;&quot;linux/amd64&quot;&lt;/span&gt;               &lt;span class=&quot;c&quot;&gt;# linux/arm64 | linux/amd64&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ $ &lt;/span&gt;docker compose &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; kong-dev-compose.yaml build kong
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;+] Building 0/1s &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0/1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                                                                                                                                                                           docker-container:multi-platform-builder
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;+] Building 59.2s &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;7/16&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                                                                                                                                                                         docker-container:multi-platform-builder
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;+] Building 93.9s &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;7/16&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                                                                                                                                                                         docker-container:multi-platform-builder
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;kong internal] booting buildkit                                                                                                                                                                                                 3.3s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; pulling image moby/buildkit:buildx-stable-1                                                                                                                                                                                   2.9s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; creating container buildx_buildkit_multi-platform-builder                                                                                                                                                                     0.4s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;kong internal] load build definition from kong-dev-compose.Dockerfile                                                                                                                                                           0.0s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; transferring dockerfile: 6.34kB                                                                                                                                                                                               0.0s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;kong internal] load metadata &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;docker.io/library/ubuntu:24.04                                                                                                                                                                 4.3s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;kong auth] library/ubuntu:pull token &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;registry-1.docker.io                                                                                                                                                                   0.0s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;kong internal] load .dockerignore                                                                                                                                                                                               0.0s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; transferring context: 2B                                                                                                                                                                                                      0.0s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;kong emmyluadebugger 1/2] FROM docker.io/library/ubuntu:24.04@sha256:80dd3c3b9c6cecb9f1667e9290b3bc61b78c2678c02cbdae5f0fea92cc6734ab                                                                                           1.9s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; resolve docker.io/library/ubuntu:24.04@sha256:80dd3c3b9c6cecb9f1667e9290b3bc61b78c2678c02cbdae5f0fea92cc6734ab                                                                                                                0.0s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; sha256:8bb55f0677778c3027fcc4253dc452bc9c22de989a696391e739fb1cdbbdb4c2 28.89MB / 28.89MB                                                                                                                                     1.4s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; extracting sha256:8bb55f0677778c3027fcc4253dc452bc9c22de989a696391e739fb1cdbbdb4c2                                                                                                                                            0.5s
 &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;kong emmyluadebugger 2/2] RUN &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt; (set -ex...)                                                                                                                                                                              84.0s
 =&amp;gt; =&amp;gt; # [ 68%] Building CXX object emmy_debugger/CMakeFiles/emmy_debugger.dir/src/transporter/transporter.cpp.o
 =&amp;gt; =&amp;gt; # [ 70%] Building CXX object emmy_debugger/CMakeFiles/emmy_debugger.dir/src/debugger/emmy_debugger.cpp.o
 =&amp;gt; =&amp;gt; # [ 71%] Building CXX object emmy_debugger/CMakeFiles/emmy_debugger.dir/src/debugger/emmy_debugger_manager.cpp.o
 =&amp;gt; =&amp;gt; # [ 73%] Building CXX object emmy_debugger/CMakeFiles/emmy_debugger.dir/src/debugger/emmy_debugger_lib.cpp.o
 =&amp;gt; =&amp;gt; # [ 75%] Building CXX object emmy_debugger/CMakeFiles/emmy_debugger.dir/src/debugger/hook_state.cpp.o
 =&amp;gt; =&amp;gt; # [ 76%] Building CXX object emmy_debugger/CMakeFiles/emmy_debugger.dir/src/debugger/extension_point.cpp.o
 =&amp;gt; [kong baseimage  2/11] RUN echo &quot;I am building target platform linux/amd64 on source platform linux/arm64 from base ubuntu:24.04&quot;

...

~ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;docker image inspect 11e108b7f310
...
&quot;Architecture&quot;: &quot;amd64&quot;,
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we do not have the multi-platform build requirement, then just stick with the default driver for better performance. Read more at &lt;a href=&quot;https://github.com/BretFisher/multi-platform-docker-build&quot;&gt;multi-platform-docker-build&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;ssh-agent-forwarding&quot;&gt;SSH Agent Forwarding&lt;/h2&gt;

&lt;p&gt;In order to &lt;a href=&quot;/2018/04/21/docker-newbie/#ssh-agent-forwarding&quot;&gt;reuse the SSH agent on the macOS host&lt;/a&gt;, we should complete two settings.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;In the section &lt;a href=&quot;#config-colima&quot;&gt;Config clima&lt;/a&gt;, we enabled the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forwardAgent, --ssh-agent&lt;/code&gt; field to forward the SSH agent on the macOS host into the colima VM.&lt;/p&gt;

    &lt;p&gt;The agent on the macOS host.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SSH_AUTH_SOCK&lt;/span&gt;
srw-------  1 jim  staff  0 Feb 28 18:05:19 2024 /var/folders/wc/fnkx5qmx61l_wx5shysmql5r0000gn/T//ssh-lNQDx9E3iDHJ/agent.90068
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The forwarded agent in the colima VM.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh colima &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;$SSH_AUTH_SOCK&apos;&lt;/span&gt;
/tmp/ssh-MwfhUrSSNj/agent.1141

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima ssh &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--very-verbose&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eval ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;$SSH_AUTH_SOCK&apos;&lt;/span&gt;
TRAC[0000] cmd &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;limactl&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;list&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;colima&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--json&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
TRAC[0000] cmd int &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;limactl&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;shell&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--workdir&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/Users/jim&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;colima&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;eval&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ls&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;-l&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SSH_AUTH_SOCK&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
srwxrwxr-x 1 jim jim 0 Jan  2 21:11 /tmp/ssh-NY12s8xDgK/agent.1142
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Additionally, within the colima VM, a symlink &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/run/host-services/ssh-auth.sock&lt;/code&gt; is created for the forwarded agent.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima ssh &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--very-verbose&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; /run/host-services/ssh-auth.sock
TRAC[0000] cmd &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;limactl&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;list&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;colima&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--json&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
TRAC[0000] cmd int &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;limactl&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;shell&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--workdir&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/Users/jim&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;colima&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;ls&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;-l&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/run/host-services/ssh-auth.sock&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
lrwxrwxrwx 1 jim root 30 Jan  2 21:11 /run/host-services/ssh-auth.sock -&amp;gt; /tmp/ssh-NY12s8xDgK/agent.1142
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The VM can resuse the forwarded SSH agent.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima ssh &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; ssh-add &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
384 SHA256:a2TyZj/tyhwUrs6JGhg//+Zwnpvti1yttted6OgmWtg jim.hu@konghq.com &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Kong Dev&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ECDSA&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
4096 SHA256:x8gO3GTWyTkJLudIvoKwHZ9Mez0BFktfSc2FZ/jGqPU jim@zhtux &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;RSA&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Bind mound the forwarded SSH agent to your container.&lt;/p&gt;

    &lt;p&gt;Containers know nothing about the SSH agent on macOS host, but the one within the colima VM.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COLIMA_SSH_AUTH_SOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;ssh colima &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;$SSH_AUTH_SOCK&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COLIMA_SSH_AUTH_SOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/run/host-services/ssh-auth.sock&apos;&lt;/span&gt;
   
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; test-ssh-agent &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;type=bind,src=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$COLIMA_SSH_AUTH_SOCK&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,dst=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$COLIMA_SSH_AUTH_SOCK&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;SSH_AUTH_SOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$COLIMA_SSH_AUTH_SOCK&lt;/span&gt; nicolaka/netshoot ssh-add &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
384 SHA256:a2TyZj/tyhwUrs6JGhg//+Zwnpvwp9yttted4OgmWtg jim.hu@konghq.com &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Kong Dev&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ECDSA&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
4096 SHA256:x2gO9GTWyTkJLudIwcFwHZ9Mez0BFktfSc9FZ/jGqPU jim@zhtux &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;RSA&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If it reports permission error, we should add the write permission &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod a+w&lt;/code&gt; to the socket file. See &lt;a href=&quot;/2018/04/21/docker-newbie/#ssh-agent-forwarding&quot;&gt;SSH Agent Forwarding&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;mount-volumes&quot;&gt;Mount Volumes&lt;/h2&gt;

&lt;p&gt;By default, the user home directory and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/colima&lt;/code&gt; are bind mounted to the VM.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/fstab | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;colima|Users&apos;&lt;/span&gt;
jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;colima|Users&apos;&lt;/span&gt;
mount0 on /Users/jim &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;virtiofs &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;rw,relatime&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
mount1 on /tmp/colima &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;virtiofs &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;rw,relatime&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Occasionally, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/colima&lt;/code&gt; mount was borken. We need to manually &lt;a href=&quot;#start-colima&quot;&gt;restart colima&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Since v0.9.0, the /tmp/colima mount is removed&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To &lt;a href=&quot;https://github.com/abiosoft/colima/blob/main/docs/FAQ.md#issue-with-docker-bind-mount-showing-empty&quot;&gt;mount other pathnames&lt;/a&gt; from macOS host to containers, we need firstly mount their parent directories to the colima VM! Otherwise, we would receive errors as follows.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;otel-collector-1  | 2025-01-07T07:42:50.770341478Z Error: cannot start pipelines: open /tmp/file_exporter.json: is a directory
otel-collector-1  | 2025-01-07T07:42:50.770344603Z 2025/01/07 07:42:50 collector server run finished with error: cannot start pipelines: open /tmp/file_exporter.json: is a directory
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mounts&lt;/code&gt; field in the &lt;a href=&quot;#config-colima&quot;&gt;config file&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;kubernetes-setup&quot;&gt;Kubernetes Setup&lt;/h1&gt;

&lt;p&gt;Regarding how to play with the Kubernetes environment, refer to &quot;biji&quot;.&lt;/p&gt;

&lt;h2 id=&quot;enable-kubernetes&quot;&gt;Enable Kubernetes&lt;/h2&gt;

&lt;p&gt;colima, under the hood, supports Kubernetes via &lt;a href=&quot;https://k3s.io/&quot;&gt;K3s&lt;/a&gt; which is a lightweight Kubernetes distribution with small memory and CPU footprint - only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;50%&lt;/code&gt; percent.&lt;/p&gt;

&lt;p&gt;To create a K8s cluster, we can add the &lt;a href=&quot;#config-colima&quot;&gt;&apos;kubernetes&apos; config field&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima template &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--editor&lt;/span&gt; nano
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;kubernetes:
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  enabled: &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As K3s server would consume extra CPU and memory. Please create a separate &lt;a href=&quot;#colima-profile&quot;&gt;profile&lt;/a&gt; for K8s specifically and start it on demand. Alternatively, we can specifiy the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--kubernetes=true&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--kubernetes=false&lt;/code&gt; CLI option. However, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--kubernetes&lt;/code&gt; CLI option would overwrite the &lt;a href=&quot;#colima-config&quot;&gt;colima config&lt;/a&gt; so that we have to always provide this CLI option.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# enable&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima start &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--kubernetes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# disable&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima start &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default &lt;span class=&quot;nt&quot;&gt;--kubernetes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Fortunately, colima supports dynamically start/stop the K8s cluster with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubernetes, k8s&lt;/code&gt; sub-command! After we stop the cluster, remember to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker container prune&lt;/code&gt; to remove the &lt;a href=&quot;#inspect-kubernetes&quot;&gt;associated dangling containers&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima status &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default
INFO[0000] colima is running using macOS Virtualization.Framework
INFO[0000] &lt;span class=&quot;nb&quot;&gt;arch&lt;/span&gt;: aarch64
INFO[0000] runtime: docker
INFO[0000] mountType: virtiofs
INFO[0000] socket: unix:///Users/jim/.colima/default/docker.sock
INFO[0000] kubernetes: enabled

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima k8s stop &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;colima status &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; default
INFO[0000] colima is running using macOS Virtualization.Framework
INFO[0000] &lt;span class=&quot;nb&quot;&gt;arch&lt;/span&gt;: aarch64
INFO[0000] runtime: docker
INFO[0000] mountType: virtiofs
INFO[0000] socket: unix:///Users/jim/.colima/default/docker.sock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can customize K3s via the &lt;a href=&quot;#config-colima&quot;&gt;&apos;k3sArgs&apos; config field&lt;/a&gt;. By default, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--disable=traefik&lt;/code&gt; (Ingress controller) is passed to the &lt;a href=&quot;https://docs.k3s.io/cli&quot;&gt;k3s server&lt;/a&gt; process.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href=&quot;https://github.com/abiosoft/colima/blob/main/docs/FAQ.md#how-does-colima-compare-to-minikube-kind-k3d&quot;&gt;FAQ&lt;/a&gt;, colima does not support multiple K8s clusters! But we can run Minikube, Kind or K3d (preferred) with colima as the backend. Alternatively, we can create multiple colima instances to simulate multiple K8s clusters.&lt;/p&gt;

&lt;h2 id=&quot;install-kubectl&quot;&gt;Install kubectl&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;kubectl

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl version
Client Version: v1.32.0
Kustomize Version: v5.5.0
Server Version: v1.31.2+k3s1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;config-kubectl&quot;&gt;Config kubectl&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl&lt;/code&gt; load config from &lt;em&gt;kubeconfig files&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--kubeconfig&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$KUBECONFIG&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${HOME}/.kube/config&lt;/code&gt; in the order of decreasing priority.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl options

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; ~/.kube/config

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl config view &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--minify&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://127.0.0.1:62005
  name: colima
contexts:
- context:
    cluster: colima
    user: colima
  name: colima
current-context: colima
kind: Config
preferences: &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;users&lt;/span&gt;:
- name: colima
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;inspect-kubernetes&quot;&gt;Inspect Kubernetes&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;colima&lt;/em&gt; K8s cluster is created.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl config get-clusters
NAME
colima

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:62005
CoreDNS is running at https://127.0.0.1:62005/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://127.0.0.1:62005/api/v1/namespaces/kube-system/services/https:metrics-server:https/proxy

To further debug and diagnose cluster problems, use &lt;span class=&quot;s1&quot;&gt;&apos;kubectl cluster-info dump&apos;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;clima&lt;/em&gt; node is created.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl get nodes &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; wide
NAME     STATUS   ROLES                  AGE   VERSION        INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
colima   Ready    control-plane,master   14d   v1.31.2+k3s1   192.168.5.1   &amp;lt;none&amp;gt;        Ubuntu 24.04.1 LTS   6.8.0-50-generic   docker://27.4.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;colima&lt;/em&gt; &lt;a href=&quot;https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/&quot;&gt;K8s context&lt;/a&gt; is created. Generally speaking, a K8s context is a combination of a cluster, a user (auth) and an optional namespace. Similar to &lt;a href=&quot;#switch-docker-engine&quot;&gt;Docker Context&lt;/a&gt;, we can switch between different K8s contexts by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kubectl config use-context&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl config current-context
colima

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl config get-contexts
CURRENT   NAME     CLUSTER   AUTHINFO   NAMESPACE
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;         colima   colima    colima
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Within the colima VM, a K3s server process is spawned.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eFF&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;k]3s
root        1794       1 14 1484594 481076 0 20:30 ?       00:05:28 /usr/local/bin/k3s server

jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;journalctl &lt;span class=&quot;nt&quot;&gt;-efx&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; k3s.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We find 3 Docker containers created for different Kubernetes internal components (e.g. CoreDNS Cluster DNS). You will find each container has an accompanying &lt;a href=&quot;biji/k8s.md#container-types&quot;&gt;pause container&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# on macOS host&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker ps
CONTAINER ID   IMAGE                        COMMAND                  CREATED          STATUS          PORTS     NAMES
b256190c220b   2f6c962e7b83                 &lt;span class=&quot;s2&quot;&gt;&quot;/coredns -conf /etc…&quot;&lt;/span&gt;   50 minutes ago   Up 50 minutes             k8s_coredns_coredns-56f6fc8fd7-jqg9q_kube-system_ba370ccf-ea61-4357-a537-bf57ad963b09_0
be7f4f0b1fe3   d3dd7baae2fc                 &lt;span class=&quot;s2&quot;&gt;&quot;local-path-provisio…&quot;&lt;/span&gt;   50 minutes ago   Up 50 minutes             k8s_local-path-provisioner_local-path-provisioner-5cf85fd84d-kh7gz_kube-system_7d860118-ebae-4964-a475-8df63e95533e_0
6a1a5c8f7902   5548a49bb60b                 &lt;span class=&quot;s2&quot;&gt;&quot;/metrics-server --c…&quot;&lt;/span&gt;   50 minutes ago   Up 50 minutes             k8s_metrics-server_metrics-server-5985cbc9d7-pqbql_kube-system_917fc3ca-e55c-4a8b-9732-3a010a337a16_0
a6d8cade10b8   rancher/mirrored-pause:3.6   &lt;span class=&quot;s2&quot;&gt;&quot;/pause&quot;&lt;/span&gt;                 50 minutes ago   Up 50 minutes             k8s_POD_metrics-server-5985cbc9d7-pqbql_kube-system_917fc3ca-e55c-4a8b-9732-3a010a337a16_0
175072564faf   rancher/mirrored-pause:3.6   &lt;span class=&quot;s2&quot;&gt;&quot;/pause&quot;&lt;/span&gt;                 50 minutes ago   Up 50 minutes             k8s_POD_coredns-56f6fc8fd7-jqg9q_kube-system_ba370ccf-ea61-4357-a537-bf57ad963b09_0
96a19292498d   rancher/mirrored-pause:3.6   &lt;span class=&quot;s2&quot;&gt;&quot;/pause&quot;&lt;/span&gt;                 50 minutes ago   Up 50 minutes             k8s_POD_local-path-provisioner-5cf85fd84d-kh7gz_kube-system_7d860118-ebae-4964-a475-8df63e95533e_0

&lt;span class=&quot;c&quot;&gt;# within colima VM&lt;/span&gt;
jim@colima:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eF&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--forest&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-A1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;c]ontainerd-shim-runc-v2
root        2444       1  0 309386 13576  2 20:30 ?        00:00:01 /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; 96a19292498d036eb229cafba53fab0f5f61736b37c1f7d0379f68b978a38e75 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
65535       2509    2444  0   190   384   0 20:30 ?        00:00:00  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /pause
root        2445       1  0 309450 13528  2 20:30 ?        00:00:01 /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; a6d8cade10b8e260d6d0217036222e081f646648f7cfe28a14ff988d32942fa9 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
65535       2508    2445  0   190   384   0 20:30 ?        00:00:00  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /pause
root        2446       1  0 309450 13492  2 20:30 ?        00:00:01 /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; 175072564faf2eb02f25385fa8e3fc8615c54999e22fdc4a389c2ad9ca0b17ec &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
65535       2507    2446  0   190   384   1 20:30 ?        00:00:00  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /pause
root        2711       1  0 309450 13896  2 20:30 ?        00:00:03 /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; be7f4f0b1fe33a4fb2b38d0c5cf7e45a654aef517824652efcd439ea6e360684 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
root        2770    2711  0 316386 33920  1 20:30 ?        00:00:02  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; local-path-provisioner start &lt;span class=&quot;nt&quot;&gt;--config&lt;/span&gt; /etc/config/config.json
root        2731       1  0 309450 14292  2 20:30 ?        00:00:03 /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; 6a1a5c8f790287a28c6d0650096f8caf23815d7c8ba984bf7b7bd4a9dae506f8 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
1000        2802    2731  1 320556 59672  0 20:30 ?        00:00:33  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /metrics-server &lt;span class=&quot;nt&quot;&gt;--cert-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tmp &lt;span class=&quot;nt&quot;&gt;--secure-port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10250 &lt;span class=&quot;nt&quot;&gt;--kubelet-preferred-address-types&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;InternalIP,ExternalIP,Hostname &lt;span class=&quot;nt&quot;&gt;--kubelet-use-node-status-port&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--metric-resolution&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;15s &lt;span class=&quot;nt&quot;&gt;--tls-cipher-suites&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
root        2751       1  0 309450 13928  2 20:30 ?        00:00:03 /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; b256190c220bb96392fee9100b55b311900e88ab79acd1ba3f890e5b21a2b8a1 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
65532       2795    2751  0 321216 52356  3 20:30 ?        00:00:17  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /coredns &lt;span class=&quot;nt&quot;&gt;-conf&lt;/span&gt; /etc/coredns/Corefile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Correspondingly, we find the associated 3 deployments and services.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ $ &lt;/span&gt;kubectl get deployments &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt;
NAMESPACE     NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
kube-system   coredns                  1/1     1            1           14d
kube-system   local-path-provisioner   1/1     1            1           14d
kube-system   metrics-server           1/1     1            1           14d

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kubectl get services &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt;
NAMESPACE     NAME             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;S&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;                  AGE
default       kubernetes       ClusterIP   10.43.0.1      &amp;lt;none&amp;gt;        443/TCP                  14d
kube-system   kube-dns         ClusterIP   10.43.0.10     &amp;lt;none&amp;gt;        53/UDP,53/TCP,9153/TCP   14d
kube-system   metrics-server   ClusterIP   10.43.39.244   &amp;lt;none&amp;gt;        443/TCP                  14d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Especially, with the &lt;a href=&quot;#introduction&quot;&gt;default runtime&lt;/a&gt;, colima and K3s share container images!&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker images &lt;span class=&quot;s1&quot;&gt;&apos;rancher/*&apos;&lt;/span&gt;
REPOSITORY                         TAG                    IMAGE ID       CREATED         SIZE
rancher/klipper-helm               v0.9.3-build20241008   128d0eddd2c8   2 months ago    188MB
rancher/local-path-provisioner     v0.0.30                d3dd7baae2fc   3 months ago    51.7MB
rancher/mirrored-library-traefik   2.11.10                43b65488db50   3 months ago    165MB
rancher/mirrored-metrics-server    v0.7.2                 5548a49bb60b   4 months ago    65.5MB
rancher/mirrored-coredns-coredns   1.11.3                 2f6c962e7b83   5 months ago    60.2MB
rancher/klipper-lb                 v0.4.9                 8e8709f8caae   5 months ago    20MB
rancher/mirrored-library-busybox   1.36.1                 7db2ddde018a   19 months ago   4.04MB
rancher/mirrored-pause             3.6                    7d46a07936af   3 years ago     484kB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We also found a Docker network is created.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker network &lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;NETWORK ID     NAME              DRIVER    SCOPE
7be6cae2031a   k3d-k3s-default   bridge    &lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;extreme-caution&quot;&gt;EXTREME CAUTION&lt;/h2&gt;

&lt;p&gt;As the Docker context and the K8s context share the same colima engine, please pay extreme caution to destruction operations like &lt;em&gt;prune&lt;/em&gt;, &lt;em&gt;rm&lt;/em&gt;, &lt;em&gt;stop&lt;/em&gt;, &lt;em&gt;kill&lt;/em&gt;, etc.&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/abiosoft/colima/blob/main/docs/FAQ.md&quot;&gt;colima FAQ&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Nginx SSLKEYLOGFILE</title>
   <link href="/2024/12/23/sslkeylogfile/"/>
   <updated>2024-12-23T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2024/12/23/sslkeylogfile</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#sslkeylogfile&quot; id=&quot;markdown-toc-sslkeylogfile&quot;&gt;SSLKEYLOGFILE&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sslkeylogc&quot; id=&quot;markdown-toc-sslkeylogc&quot;&gt;sslkeylog.c&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#compose-dockerfile&quot; id=&quot;markdown-toc-compose-dockerfile&quot;&gt;Compose Dockerfile&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#build-custom-image&quot; id=&quot;markdown-toc-build-custom-image&quot;&gt;Build Custom Image&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#decrypt-curl-traffic&quot; id=&quot;markdown-toc-decrypt-curl-traffic&quot;&gt;Decrypt cURL Traffic&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#decrypt-curl-tls-13&quot; id=&quot;markdown-toc-decrypt-curl-tls-13&quot;&gt;Decrypt cURL TLS 1.3&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#decrypt-curl-tls-12&quot; id=&quot;markdown-toc-decrypt-curl-tls-12&quot;&gt;Decrypt cURL TLS 1.2&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#decrypt-kong-traffic&quot; id=&quot;markdown-toc-decrypt-kong-traffic&quot;&gt;Decrypt Kong Traffic&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#create-kong-container&quot; id=&quot;markdown-toc-create-kong-container&quot;&gt;Create Kong Container&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#decrypt-kong-tls-13&quot; id=&quot;markdown-toc-decrypt-kong-tls-13&quot;&gt;Decrypt Kong TLS 1.3&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#references&quot; id=&quot;markdown-toc-references&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this post, I will walk you through a step-by-step tutorial on how to decrypt TLS traffic of Nginx and its variations.&lt;/p&gt;

&lt;h1 id=&quot;sslkeylogfile&quot;&gt;SSLKEYLOGFILE&lt;/h1&gt;

&lt;p&gt;Environment variable &quot;SSLKEYLOGFILE&quot; points to a pathname storing the TLS (Pre)MasterSecret (Session Secret) that can be used to decrypt TLS traffic when combined with the captured TLS handshake information.&lt;/p&gt;

&lt;p&gt;Generally speaking, there are three ways to support &quot;SSLKEYLOGFILE&quot;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Capture TLS traffic on client side.&lt;/p&gt;

    &lt;p&gt;Clients like mitmproxy (TLS proxy), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s_client -keylogfile&lt;/code&gt;, cURL, Firefox, Chrome, etc. all natively support &quot;SSLKEYLOGFILE&quot;. So, we just need to set this variable before launching the client and before capturing the TLS traffic.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Capture TLS traffic on Nginx side.&lt;/p&gt;

    &lt;p&gt;Nginx by default does not provide the ability to dump the TLS (Pre)MasterSecret. We have to hack the OpenSSL library.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Make use of 3rd-party Nginx modules like &lt;a href=&quot;https://github.com/tiandrey/nginx-sslkeylog&quot;&gt;nginx-sslkeylog&lt;/a&gt;. There is another similar patch available at &lt;a href=&quot;https://mailman.nginx.org/pipermail/nginx-devel/2024-January/W5CRPNYOC72XXFF45KQSD3VNNMGJ4WMR.html&quot;&gt;PATCH SSL: Added SSLKEYLOGFILE key material to debug logging&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;Preload &lt;a href=&quot;#sslkeylogc&quot;&gt;sslkeylog.c&lt;/a&gt;. Compared to method 2.1, it does not require patching and building. It uses &lt;a href=&quot;https://man7.org/linux/man-pages/man8/ld.so.8.html&quot;&gt;LD_PRELOAD&lt;/a&gt; to preload a newly built shared library that could dump TLS (Pre)MasterSecret if &quot;SSLKEYLOGFILE&quot; is present.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Make use of &lt;a href=&quot;https://security.stackexchange.com/a/80174/248863&quot;&gt;GDB to read TLS (Pre)MasterSecret from core dump&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;OpenSSL 3.5 onwards support &quot;SSLKEYLOGFILE&quot; via the &lt;a href=&quot;https://github.com/openssl/openssl/pull/25297&quot;&gt;enable-sslkeylog&lt;/a&gt; configure option!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This post focuses on the method 2.2.&lt;/p&gt;

&lt;h1 id=&quot;sslkeylogc&quot;&gt;sslkeylog.c&lt;/h1&gt;

&lt;p&gt;In this section, I will build a shared library &quot;libsslkeylog.so&quot; from GitHub repo &lt;a href=&quot;https://github.com/Lekensteyn/wireshark-notes/tree/master/src&quot;&gt;sslkeylog.c&lt;/a&gt;. The shared library can dump TLS (Pre)MasterSecret if it is preloaded to Nginx and the environment variable &quot;SSLKEYLOGFILE&quot; is imported into &quot;nginx.conf&quot;.&lt;/p&gt;

&lt;p&gt;I will use Nginx&apos;s derivation Kong Gateway and Docker image to demonstrate the details.&lt;/p&gt;

&lt;h2 id=&quot;compose-dockerfile&quot;&gt;Compose Dockerfile&lt;/h2&gt;

&lt;p&gt;The Dockerfile is available at &lt;a href=&quot;https://gist.github.com/outsinre/bde97c641b1830bb2d4207176ab29969&quot;&gt;sslkeylogfile.Dockerfile&lt;/a&gt;. In the build stage, the script &lt;a href=&quot;#decrypt-curl-traffic&quot;&gt;sslkeylog.sh&lt;/a&gt; is used to verify the shared library &quot;libsslkeylog.so&quot;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./sslkeylog.sh curl -sI https://www.google.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The test output from the &lt;a href=&quot;#build-custom-image&quot;&gt;building process&lt;/a&gt; is as follows.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#7 1.555 + ./sslkeylog.sh curl -sI https://www.google.com
#7 1.757 SERVER_HANDSHAKE_TRAFFIC_SECRET e4d298a7b78a9366948f621f7898b69e09b209144647736892987b7e78f869fe a89651be69b7df70508c77d80f5b518b4a3f337168bafe686710492e91edbca484593fb6fa8d7ad268359d14f9c9fb6c
#7 1.799 EXPORTER_SECRET e4d298a7b78a9366948f621f7898b69e09b209144647736892987b7e78f869fe e37bf351ac25efcbe23d444d9aec1449f16d2aceb69b582ec9623b17343bc3f32161a4f2979694890a141ad11e78cfdf
#7 1.799 SERVER_TRAFFIC_SECRET_0 e4d298a7b78a9366948f621f7898b69e09b209144647736892987b7e78f869fe f8035f7c40f19398f09a0159e4c20d868bb688ef2a176fac4f5312458b7faadf4937c2111450995f2597bff706686fd3
#7 1.799 CLIENT_HANDSHAKE_TRAFFIC_SECRET e4d298a7b78a9366948f621f7898b69e09b209144647736892987b7e78f869fe 5a37d7ae206380701b6d6ab5c12ddfe3a35def0acd7e4497e8dfe926ce19a30ed978d34d3de3530b771efdba403e11c9
#7 1.799 CLIENT_TRAFFIC_SECRET_0 e4d298a7b78a9366948f621f7898b69e09b209144647736892987b7e78f869fe 59c8486ac85d3172b21bf18834b49a606616bfa8a881afd5b25287a171f9fd6a394506cc625172af769fdbd7ff88d6cd
#7 1.899 HTTP/2 200
#7 1.899 content-type: text/html; charset=ISO-8859-1
#7 1.899 content-security-policy-report-only: object-src &apos;none&apos;;base-uri &apos;self&apos;;script-src &apos;nonce-1uCcl_kqI4AgRQc8nm8x8A&apos; &apos;strict-dynamic&apos; &apos;report-sample&apos; &apos;unsafe-eval&apos; &apos;unsafe-inline&apos; https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
#7 1.899 accept-ch: Sec-CH-Prefers-Color-Scheme
#7 1.899 p3p: CP=&quot;This is not a P3P policy! See g.co/p3phelp for more info.&quot;
#7 1.899 date: Tue, 24 Dec 2024 03:25:09 GMT
#7 1.899 server: gws
#7 1.899 x-xss-protection: 0
#7 1.899 x-frame-options: SAMEORIGIN
#7 1.899 expires: Tue, 24 Dec 2024 03:25:09 GMT
#7 1.899 cache-control: private
#7 1.899 set-cookie: AEC=AZ6Zc-VxxkKIvZWzk6Etrr2TaoT-NbBl22ugcfxfOObaAIFDKw3slf3ZTA; expires=Sun, 22-Jun-2025 03:25:09 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax
#7 1.899 set-cookie: NID=520=gulgYq_BY9y4P9xdlBnruMrbIl078sk3z4lF_A6bXpsvDoA5F6zzsEQLy1dSQOswGfITfIequq5TiTQ6nud7F4PbPXmDHRsTC5TUIUjbpZaX-33Wn8Ebj0xtT_p5zz-p-TofTwPaFTkfRWz2yOrUZdDIbXw-fxZrCkLPWUf400FskSA7Ef9rLsEi47NCb-FS; expires=Wed, 25-Jun-2025 03:25:09 GMT; path=/; domain=.google.com; HttpOnly
#7 1.899 alt-svc: h3=&quot;:443&quot;; ma=2592000,h3-29=&quot;:443&quot;; ma=2592000
#7 1.899
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We will cover more details on the verification script laster on.&lt;/p&gt;

&lt;h2 id=&quot;build-custom-image&quot;&gt;Build Custom Image&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ BUILDKIT_PROGRESS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;plain docker buildx build &lt;span class=&quot;nt&quot;&gt;--no-cache&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--load&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;kong-custom:3.9.0.0&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; sslkeylogfile.Dockerfile &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker images &lt;span class=&quot;s1&quot;&gt;&apos;kong-custom&apos;&lt;/span&gt;
REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
kong-custom   3.9.0.0   b85219c906ce   34 minutes ago   498MB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;decrypt-curl-traffic&quot;&gt;Decrypt cURL Traffic&lt;/h2&gt;

&lt;p&gt;Create a container against the custom image and locate the shared library &quot;libsslkeylog.so&quot;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; sslkeylogfile &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--entrypoint&lt;/span&gt; /bin/bash &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; kong-custom:3.9.0.0

kong@72a118f01128:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kong version
Kong Enterprise 3.9.0.0

kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; libsslkeylog.so
&lt;span class=&quot;nt&quot;&gt;-rwxr-xr-x&lt;/span&gt; 1 root root 71736 Dec 24 03:25 libsslkeylog.so
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Copy the verification script &lt;a href=&quot;https://github.com/Lekensteyn/wireshark-notes/blob/master/src/sslkeylog.sh&quot;&gt;sslkeylog.sh&lt;/a&gt; to the directory of the shared library - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/kong/lib&lt;/code&gt;. You can optionally provide &quot;SSLKEYLOGFILE&quot; to specify a pathname, otherwise the dumped (Pre)MasterSecret is printed to the stderr.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;
/usr/local/kong/lib

kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nano &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; sslkeylog.sh
...

kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x sslkeylog.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As stated above, cURL native supports &quot;SSLKEYLOGFILE&quot;, without the help of the newly built shared library &quot;libsslkeylog.so&quot;. However, the shared library can also dump TLS (Pre)MasterSecret if it is &lt;a href=&quot;https://github.com/Lekensteyn/wireshark-notes/blob/b166e14c2bf79f4a61cbcd01ca92a2c418ac9550/src/sslkeylog.sh#L62C12-L62C22&quot;&gt;preloaded&lt;/a&gt; and &quot;SSLKEYLOGFILE&quot; is set. Hence, we use cURL to verify the shared library works as expected.&lt;/p&gt;

&lt;h3 id=&quot;decrypt-curl-tls-13&quot;&gt;Decrypt cURL TLS 1.3&lt;/h3&gt;

&lt;p&gt;Start traffic capturing.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; testsslkeylogfile &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--network&lt;/span&gt; container:sslkeylogfile &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;,src&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/misc&quot;&lt;/span&gt;,dst&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tcpdump &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; nicolaka/netshoot
8ae6e4e769ae4bb6ecf705f6c96de9f78f74971ce7ec29c329e0516b12af8469

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; testsslkeylogfile bash
72a118f01128:~# &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /tcpdump/
72a118f01128:/tcpdump# tcpdump &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; any port 443 &lt;span class=&quot;nt&quot;&gt;-Uw&lt;/span&gt; sslkeylogfile.pcap
tcpdump: data &lt;span class=&quot;nb&quot;&gt;link type &lt;/span&gt;LINUX_SLL2
tcpdump: listening on any, link-type LINUX_SLL2 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Linux cooked v2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, snapshot length 262144 bytes
^C27 packets captured
27 packets received by filter
0 packets dropped by kernel
72a118f01128:/tcpdump# &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; sslkeylogfile.pcap
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt;    1 root     root          8938 Dec 24 06:47 sslkeylogfile.pcap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Trigger the request.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;:&amp;gt; /tmp/premaster.txt

kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ SSLKEYLOGFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tmp/premaster.txt ./sslkeylog.sh /usr/local/kong-tools/bin/curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--tlsv1&lt;/span&gt;.3 https://www.google.com
HTTP/2 200
content-type: text/html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ISO-8859-1
content-security-policy-report-only: object-src &lt;span class=&quot;s1&quot;&gt;&apos;none&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;base-uri &lt;span class=&quot;s1&quot;&gt;&apos;self&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;script-src &lt;span class=&quot;s1&quot;&gt;&apos;nonce-DUWj1U9UPGVMwCY29p_R8Q&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;strict-dynamic&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;report-sample&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;unsafe-eval&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;unsafe-inline&apos;&lt;/span&gt; https: http:&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;report-uri https://csp.withgoogle.com/csp/gws/other-hp
accept-ch: Sec-CH-Prefers-Color-Scheme
p3p: &lt;span class=&quot;nv&quot;&gt;CP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;This is not a P3P policy! See g.co/p3phelp for more info.&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;: Tue, 24 Dec 2024 06:30:07 GMT
server: gws
x-xss-protection: 0
x-frame-options: SAMEORIGIN
expires: Tue, 24 Dec 2024 06:30:07 GMT
cache-control: private
set-cookie: &lt;span class=&quot;nv&quot;&gt;AEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;AZ6Zc-Xnia3ReOwqLapj8yFlujpG9zCCT-Rq3eBye07oMwzr-WLr1OnluLA&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Sun, 22-Jun-2025 06:30:07 GMT&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;.google.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; Secure&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; HttpOnly&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;SameSite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;lax
set-cookie: &lt;span class=&quot;nv&quot;&gt;NID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;520&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;aAOm9hYIhcaWIbS4Mfxf3juDrMpiQJUc8Zs0TTLliXo1wgOdaqmqfaHsrSWvRU8gWzmrR0gwqxBySnfQHrgt7_aS8lIiu1yYnU06APwBYMcv6kFvmCR6w1H8100azBwocZ4ScXG6-NqPj8T13hkMZNn-1Noi4TCdXRfzIZZqsygShH_hQ50vnjGiNdjOkeE&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Wed, 25-Jun-2025 06:30:07 GMT&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;.google.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; HttpOnly
alt-svc: &lt;span class=&quot;nv&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;:443&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ma&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2592000,h3-29&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;:443&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ma&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2592000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each TLS 1.3 session needs 5 session secrets to decrypt traffic.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /tmp/premaster.txt
&lt;span class=&quot;c&quot;&gt;# SSL key logfile generated by sslkeylog.c&lt;/span&gt;
SERVER_HANDSHAKE_TRAFFIC_SECRET 6755ae538171e4100113858b989890d9ddbbb80a5f71180f8c45c5d29220d538 bc84ec978a446acf0b0da5a674b236b75d73ba0bcb949ebb8c73edf127987b8fec8af48c24e4995485c4132ae865ad8e
EXPORTER_SECRET 6755ae538171e4100113858b989890d9ddbbb80a5f71180f8c45c5d29220d538 9b14d21410073a8d7f9f1e8b6885d8240b7cfbf723a709fa538382fd4a4a01d5f8c70752817a5a4b7db5626d8b504e6f
SERVER_TRAFFIC_SECRET_0 6755ae538171e4100113858b989890d9ddbbb80a5f71180f8c45c5d29220d538 c5a31a6c65853d4386c31d2916bfb6e8a4bd900c3195ecb7daf41e613346cf24fdf3bbeca05b4e02f8c898c942bf0d9f
CLIENT_HANDSHAKE_TRAFFIC_SECRET 6755ae538171e4100113858b989890d9ddbbb80a5f71180f8c45c5d29220d538 c05914e620691f1020342c45e1177f113f88281a90885c40f5e5e6f5d102774b0b362c399a589be9174699f7cd63d3e5
CLIENT_TRAFFIC_SECRET_0 6755ae538171e4100113858b989890d9ddbbb80a5f71180f8c45c5d29220d538 1848c3e4cd96112141cafd0a89212e839a258be5b409701ca4e3fe6531e08448de2ea9f95b293a4c0eb091e12446050d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let&apos;s import the dumped (Pre)MasterSecret into the PCAP file.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;14:50:44 jim@Jims-MacBook-Pro ~/misc
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; sslkeylogfile.pcap
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt;  1 jim  staff  8938 Dec 24 14:47 sslkeylogfile.pcap

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;cp &lt;/span&gt;sslkey:/tmp/premaster.txt &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Successfully copied 2.56kB to /Users/jim/misc/.

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; premaster.txt
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt;  1 jim  staff  981 Dec 24 14:47 premaster.txt

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;editcap &lt;span class=&quot;nt&quot;&gt;--inject-secrets&lt;/span&gt; tls,premaster.txt sslkeylogfile.pcap sslkeylogfile-dsb.pcap

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; sslkeylogfile-dsb.pcap
&lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt;  1 jim  staff  10472 Dec 24 15:05 sslkeylogfile-dsb.pcap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use Wireshark to decrypt and analyze the TLS traffic.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/curl-libsslkeylog-dsb.png&quot; alt=&quot;curl-libsslkeylog-dsb.png&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;decrypt-curl-tls-12&quot;&gt;Decrypt cURL TLS 1.2&lt;/h3&gt;

&lt;p&gt;Decrypting traffic of TLS 1.2 is almost the same as decrypting the traffic of TLS 1.3. I will leave this part to you.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;:&amp;gt; /tmp/premaster.txt

kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ SSLKEYLOGFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tmp/premaster.txt ./sslkeylog.sh /usr/local/kong-tools/bin/curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--tlsv1&lt;/span&gt;.2 &lt;span class=&quot;nt&quot;&gt;--tls-max&lt;/span&gt; 1.2 https://www.google.com
HTTP/2 200
content-type: text/html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ISO-8859-1
content-security-policy-report-only: object-src &lt;span class=&quot;s1&quot;&gt;&apos;none&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;base-uri &lt;span class=&quot;s1&quot;&gt;&apos;self&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;script-src &lt;span class=&quot;s1&quot;&gt;&apos;nonce-zXzn-lr53oUa0iPPjL-jYg&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;strict-dynamic&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;report-sample&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;unsafe-eval&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;unsafe-inline&apos;&lt;/span&gt; https: http:&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;report-uri https://csp.withgoogle.com/csp/gws/other-hp
accept-ch: Sec-CH-Prefers-Color-Scheme
p3p: &lt;span class=&quot;nv&quot;&gt;CP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;This is not a P3P policy! See g.co/p3phelp for more info.&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;: Tue, 24 Dec 2024 06:35:02 GMT
server: gws
x-xss-protection: 0
x-frame-options: SAMEORIGIN
expires: Tue, 24 Dec 2024 06:35:02 GMT
cache-control: private
set-cookie: &lt;span class=&quot;nv&quot;&gt;AEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;AZ6Zc-XYq2E4RNGSN48i3AiXeBdwUJJsDimdVa_UQSnVCt2Rx6fqu1j1Lg&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Sun, 22-Jun-2025 06:35:02 GMT&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;.google.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; Secure&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; HttpOnly&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;SameSite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;lax
set-cookie: &lt;span class=&quot;nv&quot;&gt;NID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;520&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Vn8bZrsr2eiT_doMDp6KS8Jvo5lXFMX2z-acFRLxWxwYuGfnFWKwdmd8Y8eZV-kgphfnmPqVjW-0689KjGfUmcZVSHsuz-JMFKxN3CIbczHD2VIJqywOBeIZv3ef5IHr0MdcKNvJffcra9mp-X3QFolGZUylIbjkRybTgY14OIUVfZ2pr3tXSAKVKGk2OCE&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Wed, 25-Jun-2025 06:35:02 GMT&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;.google.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; HttpOnly
alt-svc: &lt;span class=&quot;nv&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;:443&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ma&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2592000,h3-29&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;:443&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ma&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2592000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pay attention that each TLS 1.2 session needs just 1 session secret to decrypt traffic.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kong@72a118f01128:/usr/local/kong/lib&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /tmp/premaster.txt
&lt;span class=&quot;c&quot;&gt;# SSL key logfile generated by sslkeylog.c&lt;/span&gt;
CLIENT_RANDOM 373ad1cfde82cc6ac98ed54f3b5dbfda9eabee9fe49886b1d3c040aa7bef7ddd 6f526e02d325fbaf0e5406ba6f644ba5c8d5a3c8d2fb534913ba47d9ed8f97f5fff36a058f7625cd974d3fea508d2d43
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;decrypt-kong-traffic&quot;&gt;Decrypt Kong Traffic&lt;/h2&gt;

&lt;p&gt;Before, we start Kong, we need three special settings.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Set the environment variable &quot;SSLKEYLOGFILE&quot;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SSLKEYLOGFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/kong/pre-mastersecret.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;As we &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt;, it affects all child processes launched in this terminal. Avoid this by prepending the variable to &quot;kong start&quot;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;env &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SSLKEYLOGFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/kong/pre-mastersecret.txt kong start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If Kong is deployed with Helm Charts, set it in the Helm values.&lt;/p&gt;

    &lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;customEnv&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;SSLKEYLOGFILE&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/usr/local/kong/pre-mastersecret.txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If Kong is managed by systemd, then &lt;a href=&quot;/2021/07/19/systemd/#systemd-drop-in&quot;&gt;insert&lt;/a&gt; the the variable to &quot;kong-enterprise-edition.service&quot;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl edit kong-enterprise-edition.service
&lt;span class=&quot;c&quot;&gt;### Editing /etc/systemd/system/kong-enterprise-edition.service.d/override.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;### Anything between here and the comment below will become the new contents of the file&lt;/span&gt;
...
&lt;span class=&quot;nv&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SSLKEYLOGFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/kong/pre-mastersecret.txt
...

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Let Kong &lt;a href=&quot;http://nginx.org/en/docs/ngx_core_module.html#env&quot;&gt;inherit the environment variable&lt;/a&gt; by inserting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env SSLKEYLOGFILE;&lt;/code&gt; into &quot;nginx.conf&quot;. It is a must as Nginx removes all environment variables inherited from its parent process except the &quot;TZ&quot; variable.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;KONG_NGINX_MAIN_ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;SSLKEYLOGFILE
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;env &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;KONG_NGINX_MAIN_ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;SSLKEYLOGFILE kong start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If Kong is deployed with Helm Charts, configure it in the Helm values.&lt;/p&gt;

    &lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;nginx_main_env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;SSLKEYLOGFILE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If Kong is managed by systemd, then &lt;a href=&quot;/2021/07/19/systemd/#systemd-drop-in&quot;&gt;insert&lt;/a&gt; the the variable to &quot;kong-enterprise-edition.service&quot;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl edit kong-enterprise-edition.service
&lt;span class=&quot;c&quot;&gt;### Editing /etc/systemd/system/kong-enterprise-edition.service.d/override.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;### Anything between here and the comment below will become the new contents of the file&lt;/span&gt;
...
&lt;span class=&quot;nv&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;KONG_NGINX_MAIN_ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;SSLKEYLOGFILE
...

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Preload the shared library &quot;libsslkeylog.so&quot; for Kong.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LD_PRELOAD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/kong/lib/libsslkeylog.so
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;As we &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt;, it affects all child processes launched in this terminal. Avoid this by prepending the variable to &quot;kong start&quot;, or use the dynamic loader &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld.so&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld-linux.so&lt;/code&gt; with the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--preload&lt;/code&gt; against &quot;nginx&quot;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ LD_DEBUG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;all,unused,statistics&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;LD_PRELOAD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/kong/lib/libsslkeylog.so &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
kong start

~ &lt;span class=&quot;nv&quot;&gt;$ LD_DEBUG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;all,unused,statistics&quot;&lt;/span&gt; ld.so &lt;span class=&quot;nt&quot;&gt;--preload&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/kong/lib/libsslkeylog.so&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
/usr/local/openresty/nginx/sbin/nginx &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /usr/local/kong/ &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; nginx.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If Kong is deployed with Helm Charts, do it in the Helm values.&lt;/p&gt;

    &lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;customEnv&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;LD_PRELOAD&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/usr/local/kong/lib/libsslkeylog.so&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If Kong is managed by systemd, then &lt;a href=&quot;/2021/07/19/systemd/#systemd-drop-in&quot;&gt;insert&lt;/a&gt; the the variable to &quot;kong-enterprise-edition.service&quot;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl edit kong-enterprise-edition.service
&lt;span class=&quot;c&quot;&gt;### Editing /etc/systemd/system/kong-enterprise-edition.service.d/override.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;### Anything between here and the comment below will become the new contents of the file&lt;/span&gt;
...
&lt;span class=&quot;nv&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LD_PRELOAD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/kong/lib/libsslkeylog.so
...

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;create-kong-container&quot;&gt;Create Kong Container&lt;/h3&gt;

&lt;p&gt;For a demostration purpose, I will start Kong in DB-less mode. Pay attention to the three special settings.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; sslkeylogfile &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;KONG_DATABASE=off&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;KONG_LICENSE_DATA=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;KONG_LICENSE_DATA&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 http2 ssl&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8000-8001:8000-8001 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8443:8443 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SSLKEYLOGFILE=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SSLKEYLOGFILE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;/usr/local/kong/pre-mastersecret.txt&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;KONG_NGINX_MAIN_ENV=SSLKEYLOGFILE&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;LD_PRELOAD=/usr/local/kong/lib/libsslkeylog.so&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
kong-custom:3.9.0.0

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker ps &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;name=sslkeylogfile&apos;&lt;/span&gt;
CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS                        PORTS                                                            NAMES
bcf77d685ed8   kong-custom:3.9.0.0   &lt;span class=&quot;s2&quot;&gt;&quot;/entrypoint.sh kong…&quot;&lt;/span&gt;   About a minute ago   Up About a minute &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;healthy&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;   8002-8004/tcp, 0.0.0.0:8000-8001-&amp;gt;8000-8001/tcp, 8443-8447/tcp   sslkeylogfile

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; sslkeylogfile bash
kong@57d808a5eb3f:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eFH&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;n]ginx
kong         1     0  1 134701 98936  1 08:38 ?        00:00:01 nginx: master process /usr/local/openresty/nginx/sbin/nginx &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /usr/local/kong &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; nginx.conf
kong      2549     1  1 669837 129140 2 08:38 ?        00:00:01   nginx: worker process
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check if the three special settings are correctly configured.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kong@3ce3b73ed92d:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;SSLKEYLOGFILE\|KONG_NGINX_MAIN_ENV\|LD_PRELOAD&apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;SSLKEYLOGFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/kong/pre-mastersecret.txt
&lt;span class=&quot;nv&quot;&gt;KONG_NGINX_MAIN_ENV&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;SSLKEYLOGFILE
&lt;span class=&quot;nv&quot;&gt;LD_PRELOAD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/kong/lib/libsslkeylog.so

kong@57d808a5eb3f:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt; /usr/local/kong/nginx.conf
&lt;span class=&quot;nb&quot;&gt;env &lt;/span&gt;SSLKEYLOGFILE&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check if Kong correctly preloads the shared library.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kong@57d808a5eb3f:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; /usr/local/kong/lib/libsslkeylog.so
&lt;span class=&quot;nt&quot;&gt;-rwxr-xr-x&lt;/span&gt; 1 root root 71736 Dec 24 03:25 /usr/local/kong/lib/libsslkeylog.so

kong@3ce3b73ed92d:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;lsof &lt;span class=&quot;nt&quot;&gt;-nP&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 1,2550 | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;ssl
nginx      1 kong  mem       REG              254,1             2635191 /usr/local/kong/lib/libssl.so.3 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;path &lt;span class=&quot;nv&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0,216&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
nginx      1 kong  mem       REG              254,1             2642476 /usr/local/kong/lib/libsslkeylog.so &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;path &lt;span class=&quot;nv&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0,216&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
nginx   2550 kong  mem       REG              254,1             2635191 /usr/local/kong/lib/libssl.so.3 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;path &lt;span class=&quot;nv&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0,216&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
nginx   2550 kong  mem       REG              254,1             2642476 /usr/local/kong/lib/libsslkeylog.so &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;path &lt;span class=&quot;nv&quot;&gt;dev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0,216&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# even affect &quot;ls&quot; as the variable LD_PRELOAD is exported&lt;/span&gt;
kong@3ce3b73ed92d:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ldd /usr/bin/ls | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;ssl
  /usr/local/kong/lib/libsslkeylog.so &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0x0000ffffa1420000&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Load &lt;a href=&quot;https://gist.github.com/outsinre/bde97c641b1830bb2d4207176ab29969&quot;&gt;the sample runtime declarative config&lt;/a&gt; to Kong.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-sS&lt;/span&gt; localhost:8001/ | jq &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; .configuration.database
off

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-sS&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;http://localhost:8001/config?check_hash=1&amp;amp;flatten_errors=1&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--data-binary&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;@sslkeylogfile.yml&apos;&lt;/span&gt; | jq &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-sS&lt;/span&gt; http://localhost:8001/config | jq &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; .config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;decrypt-kong-tls-13&quot;&gt;Decrypt Kong TLS 1.3&lt;/h3&gt;

&lt;p&gt;The process is almost the same as that in &lt;a href=&quot;#decrypt-curl-tls-1.3&quot;&gt;Decrypt cURL TLS 1.3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Start traffic capturing.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; testsslkeylogfile &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--network&lt;/span&gt; container:sslkeylogfile &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;,src&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/misc&quot;&lt;/span&gt;,dst&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tcpdump &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; nicolaka/netshoot
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; testsslkeylogfile bash

3ce3b73ed92d:~# &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /tcpdump/
3ce3b73ed92d:/tcpdump# tcpdump &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; any port 8443 or port 443 &lt;span class=&quot;nt&quot;&gt;-Uw&lt;/span&gt; sslkeylogfile.pcap
tcpdump: data &lt;span class=&quot;nb&quot;&gt;link type &lt;/span&gt;LINUX_SLL2
tcpdump: listening on any, link-type LINUX_SLL2 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Linux cooked v2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, snapshot length 262144 bytes
^C37 packets captured
62 packets received by filter
0 packets dropped by kernel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Trigger the request.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; sslkeylogfile bash

kong@3ce3b73ed92d:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/usr/local/kong-tools/bin/curl &lt;span class=&quot;nt&quot;&gt;-ksI&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--tlsv1&lt;/span&gt;.3 https://localhost:8443/sslkeylogfile
HTTP/2 200
content-type: text/html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ISO-8859-1
content-security-policy-report-only: object-src &lt;span class=&quot;s1&quot;&gt;&apos;none&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;base-uri &lt;span class=&quot;s1&quot;&gt;&apos;self&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;script-src &lt;span class=&quot;s1&quot;&gt;&apos;nonce-G9tWrQ1duP-4WMfkwjlddA&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;strict-dynamic&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;report-sample&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;unsafe-eval&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;unsafe-inline&apos;&lt;/span&gt; https: http:&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;report-uri https://csp.withgoogle.com/csp/gws/other-hp
accept-ch: Sec-CH-Prefers-Color-Scheme
p3p: &lt;span class=&quot;nv&quot;&gt;CP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;This is not a P3P policy! See g.co/p3phelp for more info.&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;: Tue, 24 Dec 2024 10:06:07 GMT
server: gws
x-xss-protection: 0
x-frame-options: SAMEORIGIN
expires: Tue, 24 Dec 2024 10:06:07 GMT
cache-control: private
set-cookie: &lt;span class=&quot;nv&quot;&gt;AEC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;AZ6Zc-Xf9dWoag6LIHV2mWOAVhSHlj1p3KOjwiQY-m0IiYgyatxWDPvZKQ&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Sun, 22-Jun-2025 10:06:07 GMT&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;.google.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; Secure&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; HttpOnly&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;SameSite&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;lax
set-cookie: &lt;span class=&quot;nv&quot;&gt;NID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;520&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;HL3HxiTphQw9L0EG5eWpwW51t-egXIhozTYSFQf8bHQF_nt8JV93JiJjR8N8JrPrdOjYHrFTDpEKNgdKr7gvA8vE1zr99-73Egy7JBex_SX_BDbntCBGkKUrZ8pbtKIMg0BajyqcQoAtpzWXFLEcwAmuxnx7IZ1XnDFSKF_MriNXtJUO0ZgiRvr8VTtlYlY&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Wed, 25-Jun-2025 10:06:07 GMT&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;.google.com&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; HttpOnly
alt-svc: &lt;span class=&quot;nv&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;:443&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ma&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2592000,h3-29&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;:443&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ma&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2592000
x-kong-upstream-latency: 321
x-kong-proxy-latency: 9
via: 1.1 kong/3.9.0.0-enterprise-edition
x-kong-request-id: 6728f746f230033fab49d41f197f4258
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let&apos;s import the dumped (Pre)MasterSecret into the PCAP file.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;cp &lt;/span&gt;sslkeylogfile:/usr/local/kong/pre-mastersecret.txt &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Successfully copied 4.61kB to /Users/zachary/misc/.

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;editcap &lt;span class=&quot;nt&quot;&gt;--inject-secrets&lt;/span&gt; tls,pre-mastersecret.txt sslkeylogfile.pcap sslkeylogfile-dsb.pcap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use Wireshark to decrypt and analyze the TLS traffic.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/kong-libsslkeylog-dsb.png&quot; alt=&quot;kong-libsslkeylog-dsb.png&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.wireshark.org/TLS&quot;&gt;Wireshark TLS&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://security.stackexchange.com/q/216065/248863&quot;&gt;Extracting openssl pre-master secret from nginx&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>golang</title>
   <link href="/2024/11/12/golang/"/>
   <updated>2024-11-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2024/11/12/golang</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#macos&quot; id=&quot;markdown-toc-macos&quot;&gt;macOS&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gopath&quot; id=&quot;markdown-toc-gopath&quot;&gt;GOPATH&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The terminologies &quot;Go&quot; and &quot;golang&quot; might be used interchangeably throughout this post.&lt;/p&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;h2 id=&quot;macos&quot;&gt;macOS&lt;/h2&gt;

&lt;p&gt;We can &lt;a href=&quot;https://go.dev/doc/install&quot;&gt;install golang&lt;/a&gt; via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew&lt;/code&gt; or &lt;a href=&quot;https://go.dev/dl/&quot;&gt;officially built binary package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To install or upgrade golang with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;go|golang

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;go
go is hashed &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;/opt/homebrew/bin/go&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;go version
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;go &lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew upgrade go|golang
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For the second method, just download and click the binary (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go1.23.3.darwin-arm64.tar.gz&lt;/code&gt;). It will prompts us to install golang in the system directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/go&lt;/code&gt;, for all users. For update, just repeat the same process.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;go
go is hashed &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;/usr/local/go/bin/go&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;gopath&quot;&gt;GOPATH&lt;/h1&gt;

&lt;p&gt;The variable &lt;a href=&quot;https://go.dev/wiki/GOPATH&quot;&gt;GOPATH&lt;/a&gt; is a pathname for installing extra modules beyond the official ones, usually residing in the user&apos;s home. It is also the place where we develop and test personal modules.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;go &lt;span class=&quot;nb&quot;&gt;env &lt;/span&gt;GOPATH
/Users/zachary/go

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$GOPATH&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls &lt;/span&gt;go/bin/
go-wrk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Interestingly, it is not a Shell environment variable, but exclusive to golang! Upon installation, the golang toolchain would automatically configure it, including the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GOPATH/bin&lt;/code&gt;. We can &lt;a href=&quot;https://stackoverflow.com/a/21506074&quot;&gt;manually configure it&lt;/a&gt; for Shell reference.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ~/.bash_profile&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOPATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/go&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOPATH&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Actually, golang maintains its own environment variables via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go env&lt;/code&gt;. These variables are stored at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.config/go/env&lt;/code&gt; (Linux) or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/Library/Application Support/go/env&lt;/code&gt; (macOS).&lt;/p&gt;

&lt;p&gt;Here is an example.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;go &lt;span class=&quot;nb&quot;&gt;env &lt;/span&gt;GOPRIVATE

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;go &lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;GOPRIVATE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;github.com/kong/,github.com/Kong/&apos;&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; ~/Library/Application&lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;Support/go/env
&lt;span class=&quot;nv&quot;&gt;GOPRIVATE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;github.com/kong/,github.com/Kong/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>GDB and Core Dump</title>
   <link href="/2024/07/25/gdb/"/>
   <updated>2024-07-25T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2024/07/25/gdb</id>
   <content type="html">&lt;p&gt;This is a tutorial on dynamically analyzing and exploiting &lt;em&gt;objects&lt;/em&gt; with GDB (GNU DeBugger). Without explicit notice, the object type is Core Dump. The term &quot;object&quot; and the term &quot;executable&quot; are used interchangably in this post.&lt;/p&gt;

&lt;p&gt;Please playaround with the code in the &lt;a href=&quot;#appendix&quot;&gt;Appendix section&lt;/a&gt;.&lt;/p&gt;

&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#limitations&quot; id=&quot;markdown-toc-limitations&quot;&gt;Limitations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gdb-extensions&quot; id=&quot;markdown-toc-gdb-extensions&quot;&gt;GDB Extensions&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#gef&quot; id=&quot;markdown-toc-gef&quot;&gt;gef&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#pwndbg&quot; id=&quot;markdown-toc-pwndbg&quot;&gt;pwndbg&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#openresty-gdb-utils&quot; id=&quot;markdown-toc-openresty-gdb-utils&quot;&gt;openresty-gdb-utils&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#nginxgdb&quot; id=&quot;markdown-toc-nginxgdb&quot;&gt;nginx.gdb&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gdb-configuration&quot; id=&quot;markdown-toc-gdb-configuration&quot;&gt;GDB Configuration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#objects-with-debug-info&quot; id=&quot;markdown-toc-objects-with-debug-info&quot;&gt;Objects with Debug Info&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#core-dump&quot; id=&quot;markdown-toc-core-dump&quot;&gt;Core Dump&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#verify-core-dump&quot; id=&quot;markdown-toc-verify-core-dump&quot;&gt;Verify Core Dump&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#quickstart&quot; id=&quot;markdown-toc-quickstart&quot;&gt;Quickstart&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#launch-a-process&quot; id=&quot;markdown-toc-launch-a-process&quot;&gt;Launch a Process&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#trace-a-process&quot; id=&quot;markdown-toc-trace-a-process&quot;&gt;Trace a Process&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#load-a-core-dump&quot; id=&quot;markdown-toc-load-a-core-dump&quot;&gt;Load a Core Dump&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gdb-commands&quot; id=&quot;markdown-toc-gdb-commands&quot;&gt;GDB Commands&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#more-tools&quot; id=&quot;markdown-toc-more-tools&quot;&gt;More Tools&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#hexdump&quot; id=&quot;markdown-toc-hexdump&quot;&gt;hexdump&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#strings&quot; id=&quot;markdown-toc-strings&quot;&gt;strings&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#readelf&quot; id=&quot;markdown-toc-readelf&quot;&gt;readelf&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#objdump&quot; id=&quot;markdown-toc-objdump&quot;&gt;objdump&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#memory&quot; id=&quot;markdown-toc-memory&quot;&gt;Memory&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#nginx&quot; id=&quot;markdown-toc-nginx&quot;&gt;Nginx&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#appendix&quot; id=&quot;markdown-toc-appendix&quot;&gt;Appendix&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;limitations&quot;&gt;Limitations&lt;/h1&gt;

&lt;p&gt;GDB currently does not support Apple Arm chipset (e.g. M1). To bypass this blocker, we can run GDB within Docker container on M1.&lt;/p&gt;

&lt;p&gt;However, attaching a tracee process (e.g. Nginx worker) to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcore&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb&lt;/code&gt; tracer process within containerized environment is limited by the &lt;a href=&quot;https://gist.github.com/outsinre/d2b58b289425fbdd2d0f0294f3fdf0c9&quot;&gt;kernel.yama.ptrace_scope&lt;/a&gt; kernel parameter. To resolve this limitation, we have two solutions as follows.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;For a vanilla Docker container, we should add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--privileged&lt;/code&gt; option. Alternatively, add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cap_add SYS_PTRACE&lt;/code&gt; option and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcore&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;For K8s deployment, refer to the &lt;a href=&quot;https://gist.github.com/outsinre/d2b58b289425fbdd2d0f0294f3fdf0c9&quot;&gt;Generate core dump within K8s Environment&lt;/a&gt; tutorial.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;gdb-extensions&quot;&gt;GDB Extensions&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;#gef&quot;&gt;gef&lt;/a&gt; (GDB Ehanced Features) is a Python plugin for vanilla GDB, supporting both x86 (32/64) and Arm (AArch 32/64). It comes with just a single Python script file and requires no dependencies except Python. Howeveer, some gef commands &lt;a href=&quot;https://hugsy.github.io/gef/install/&quot;&gt;depends on&lt;/a&gt; a few other tools like &lt;em&gt;file&lt;/em&gt;, &lt;em&gt;readelf&lt;/em&gt;, &lt;em&gt;nm&lt;/em&gt;, and &lt;em&gt;ps&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Its successor &lt;a href=&quot;#pwngdb&quot;&gt;pwndbg&lt;/a&gt; is more actively maintained. &lt;a href=&quot;https://github.com/longld/peda&quot;&gt;peda&lt;/a&gt;, on the other hand, is almost deprecated, and the last commit is from 4 years ago.&lt;/p&gt;

&lt;p&gt;For any extension, we can load it via &lt;a href=&quot;#gdb-configuration&quot;&gt;GDB configuration&lt;/a&gt; at startup, or load it interactively after startup.&lt;/p&gt;

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

&lt;p&gt;Before using &lt;a href=&quot;https://github.com/hugsy/gef&quot;&gt;gef&lt;/a&gt;, ensure the following tools are available in your system.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;file
readelf
nm
ps
python3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Additionally, ensure the locale is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UTF-8&lt;/code&gt;, otherwise gef reports &quot;UnicodeEncodeError&quot;. See &lt;a href=&quot;https://github.com/hugsy/gef/issues/195&quot;&gt;https://github.com/hugsy/gef/issues/195&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can download gef from the official repo.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ubuntu@ip-172-31-9-194:~/workspace/ git clone https://github.com/hugsy/gef

ubuntu@ip-172-31-9-194:~/workspace&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;gef/
ubuntu@ip-172-31-9-194:~/workspace/gef&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;LICENSE  README.md  docs  gef.py  mkdocs.yml  scripts  tests
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The only file required is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gef.py&lt;/code&gt; script. We can load &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gef.py&lt;/code&gt; on the fly.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/workspace/gef/gef.py
GEF &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;linux ready, &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;gef&lt;span class=&quot;s1&quot;&gt;&apos; to start, `gef config&apos;&lt;/span&gt; to configure
93 commands loaded and 5 functions added &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;GDB 12.1 &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.00ms using Python engine 3.10
gef➤  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, load gef automatically on GDB startup.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;source /path/to/gef.py&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.config/gdb/gdbinit

ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt;
GEF &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;linux ready, &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;gef&lt;span class=&quot;s1&quot;&gt;&apos; to start, `gef config&apos;&lt;/span&gt; to configure
93 commands loaded and 5 functions added &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;GDB 12.1 &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;0.00ms using Python engine 3.10
gef➤
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At any moment, we can use the gef &lt;em&gt;context&lt;/em&gt; command to show registers, stack, code (disassembly), code, &lt;a href=&quot;#gdb-commands&quot;&gt;frames&lt;/a&gt;, etc.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  context
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/assets/gef-context.png&quot; alt=&quot;assets/gef-context.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;From the figure above, the stack is growing from high address to low address.&lt;/p&gt;

&lt;p&gt;In addition to standard GDB commands, gef offers &lt;a href=&quot;https://hugsy.github.io/gef/commands/aliases/&quot;&gt;enhanced commands&lt;/a&gt;. Use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gef&lt;/code&gt; command to list all enhanced commands.&lt;/p&gt;

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

&lt;p&gt;&lt;a href=&quot;https://github.com/pwndbg/pwndbg&quot;&gt;pwngdb&lt;/a&gt; is more powerful than its predecessor &lt;a href=&quot;#gef&quot;&gt;gef&lt;/a&gt;. However, it is a standard Linux package (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rpm&lt;/code&gt;). In order not to pollute the system LFS, we install the portable tarball that contains everything needed. The portable tarball even includes a built-in &lt;em&gt;gdb&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /tmp

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-LO&lt;/span&gt; https://github.com/pwndbg/pwndbg/releases/download/2025.04.18/pwndbg_2025.04.18_arm64-portable.tar.xz

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xJvf&lt;/span&gt; pwndbg_2025.04.18_arm64-portable.tar.xz &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; /opt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To launch pwngdb, we just run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/opt/pwndbg/bin/pwndbg&lt;/code&gt; Shell script.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /opt/pwndbg/bin/pwndbg

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/pwndbg/bin/pwndbg
pwndbg: loaded 188 pwndbg commands and 39 shell commands. Type pwndbg &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--shell&lt;/span&gt; | &lt;span class=&quot;nt&quot;&gt;--all&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;filter] &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;a list.
pwndbg: created &lt;span class=&quot;nv&quot;&gt;$rebase&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$base&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$hex2ptr&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$argv&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$envp&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$argc&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$environ&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$bn_sym&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$bn_var&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$bn_eval&lt;/span&gt;, &lt;span class=&quot;nv&quot;&gt;$ida&lt;/span&gt; GDB functions &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;can be used with print/break&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-------&lt;/span&gt; tip of the day &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;disable with &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;show-tips off&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-------&lt;/span&gt;
If your program has multiple threads they will be displayed &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the context display or using the context threads &lt;span class=&quot;nb&quot;&gt;command
&lt;/span&gt;pwndbg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Inpsecting the process, we found pwngdb use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld-linux&lt;/code&gt; dynamic loader to launch GDB with a specialized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdbinit.py&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps aux | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;g]db
kong      410273  1.1  1.0 480768 82600 pts/0    Sl+  14:14   0:00 /opt/pwndbg/lib/ld-linux-aarch64.so.1 /opt/pwndbg/exe/gdb &lt;span class=&quot;nt&quot;&gt;--quiet&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--early-init-eval-command&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;auto-load safe-path / &lt;span class=&quot;nt&quot;&gt;--command&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/opt/pwndbg/exe/gdbinit.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;openresty-gdb-utils&quot;&gt;openresty-gdb-utils&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/api7/openresty-gdb-utils&quot;&gt;openresty-gdb-utils&lt;/a&gt; is another GDB extension to debug OpenResty programs, including Nginx, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ngx_lua&lt;/code&gt;, LuaJIT, etc.&lt;/p&gt;

&lt;p&gt;Regarding installation, configuration and commands, please refer to the official page.&lt;/p&gt;

&lt;h2 id=&quot;nginxgdb&quot;&gt;nginx.gdb&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/outsinre/1acf3136ee5ea4a693fac12c5e237777&quot;&gt;nginx.gdb&lt;/a&gt; is personal GDB script with a few functionalities.&lt;/p&gt;

&lt;h1 id=&quot;gdb-configuration&quot;&gt;GDB Configuration&lt;/h1&gt;

&lt;p&gt;To show the GDB installation, pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--configuration&lt;/code&gt; option.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;kong-dev&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; kong@kong-ee:/kong-ee&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb &lt;span class=&quot;nt&quot;&gt;--configuration&lt;/span&gt;
This GDB was configured as follows:
   configure &lt;span class=&quot;nt&quot;&gt;--host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;aarch64-linux-gnu &lt;span class=&quot;nt&quot;&gt;--target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;aarch64-linux-gnu
             &lt;span class=&quot;nt&quot;&gt;--with-auto-load-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$debugdir&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$datadir&lt;/span&gt;/auto-load
             &lt;span class=&quot;nt&quot;&gt;--with-auto-load-safe-path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$debugdir&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$datadir&lt;/span&gt;/auto-load
             &lt;span class=&quot;nt&quot;&gt;--with-expat&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-gdb-datadir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/share/gdb &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;relocatable&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-jit-reader-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/lib/gdb &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;relocatable&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--without-libunwind-ia64&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-lzma&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-babeltrace&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--without-intel-pt&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-xxhash&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-python&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;relocatable&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-python-libdir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/lib &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;relocatable&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-debuginfod&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-curses&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--without-guile&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--without-amd-dbgapi&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--enable-source-highlight&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--enable-threading&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--enable-tui&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-system-readline&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-separate-debug-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/lib/debug &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;relocatable&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;nt&quot;&gt;--with-system-gdbinit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/etc/gdb/gdbinit
             &lt;span class=&quot;nt&quot;&gt;--with-system-gdbinit-dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/etc/gdb/gdbinit.d

&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Relocatable&quot;&lt;/span&gt; means the directory can be moved with the GDB installation
tree, and GDB will still find it.&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To configure GDB, we have two types of configuration files.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/gdb/gdbearlyinit&lt;/code&gt; which is checked before any other GDB configuration file.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# similar to option &apos;-q&apos;
set startup-quietly on
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This kind of configuration can be replaced by CLI options.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/gdb/gdbinit&lt;/code&gt; which is the primary configuration file.&lt;/p&gt;

    &lt;p&gt;Automatically load &lt;a href=&quot;#gef&quot;&gt;gef&lt;/a&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;source /home/ubuntu/workspace/gef/gef.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Automatically load &lt;a href=&quot;#openresty-gdb-utils&quot;&gt;openresty-gdb-utils&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;directory /home/ubuntu/workspace/openresty-gdb-utils
   
py import sys
py sys.path.append(&quot;/home/ubuntu/workspace/openresty-gdb-utils&quot;)
   
source luajit20.gdb
source ngx-lua.gdb
source luajit21.py
source ngx-raw-req.py
set python print-stack full
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This kind of configuration can be replanced by interactive commands after GDB startup.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;objects-with-debug-info&quot;&gt;Objects with Debug Info&lt;/h1&gt;

&lt;p&gt;Without debug information, GDB cannot do symbol translation for names (e.g. variables and functions).&lt;/p&gt;

&lt;p&gt;When compiling an executable, we can add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ggdb3&lt;/code&gt; option to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc&lt;/code&gt; to include debug information. Additionally, we can add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-O0&lt;/code&gt; option to suppress the target machine code optimization from compiler.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;test-gdb.c
&lt;span class=&quot;c&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/span&gt;

int f&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;int a, int b&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        int &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; a + b&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

int main&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;int argc, char &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;argv[]&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;number of args: %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, argc&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;arg input: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, argv[1]&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        int x &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        int y &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 2&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        int s &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; f&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;x, y&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;%d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, s/0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gcc &lt;span class=&quot;nt&quot;&gt;-Wall&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wextra&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ggdb3&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-O0&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;c11 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; test-gdb.out test-gdb.c
test-gdb.c: In &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; ‘main’:
test-gdb.c:19:25: warning: division by zero &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Wdiv-by-zero&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
   19 |         &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;%d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;, s/0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      |                         ^

ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file test-gdb.out
test-gdb.out: ELF 64-bit LSB pie executable, x86-64, version 1 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;SYSV&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;8bfff35a0f503e12c7fa1f0ffed67597fcf3fb0c, &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;GNU/Linux 3.2.0, with debug_info, not stripped
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-ggdb3&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-O0&lt;/code&gt; options improve debug experience, but the program would be less optimized and performant. Do not do this for production.&lt;/p&gt;

&lt;h1 id=&quot;core-dump&quot;&gt;Core Dump&lt;/h1&gt;

&lt;p&gt;This post focuses on Core Dump object. It is the memory dump of a running process.&lt;/p&gt;

&lt;p&gt;There are multiple ways to get a Core Dump. For example, we can make use of the command &lt;a href=&quot;#attach-to-a-process&quot;&gt;gcore to dump the memory&lt;/a&gt;. Alternatively, we can configure the system to automatically generate a Core Dump when a program crash. Please read &quot;biji&quot; for details.&lt;/p&gt;

&lt;p&gt;Please also read the tutorial on &lt;a href=&quot;https://gist.github.com/outsinre/d2b58b289425fbdd2d0f0294f3fdf0c9&quot;&gt;How to generate Core Dump within K8s environment&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;verify-core-dump&quot;&gt;Verify Core Dump&lt;/h2&gt;

&lt;p&gt;After receiving a Core Dump file, we must validate it is legitmate.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file core_new.2436
core_new.2436: ELF 64-bit LSB core file, x86-64, version 1 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;SYSV&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, SVR4-style, from &lt;span class=&quot;s1&quot;&gt;&apos;nginx: worker prnginx: worker process&apos;&lt;/span&gt;, real uid: 1000, effective uid: 1000, real gid: 1000, effective gid: 1000, execfn: &lt;span class=&quot;s1&quot;&gt;&apos;/usr/local/openresty/nginx/sbin/nginx&apos;&lt;/span&gt;, platform: &lt;span class=&quot;s1&quot;&gt;&apos;x86_64&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Additionally, we can inspect the logical and physical disk size to see if it is &lt;a href=&quot;https://stackoverflow.com/q/43126760&quot;&gt;sparse file&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ll &lt;span class=&quot;nt&quot;&gt;-hs&lt;/span&gt; core_new.2436
747M &lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt; 1 ubuntu ubuntu 3.0G Jul 31 03:44 core_new.2436

ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;du&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-hsc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; core_new.2436
747M    core_new.2436
747M    total
ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;du&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-hsc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--apparent-size&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; core_new.2436
3.0G    core_new.2436
3.0G    total

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;stat &lt;/span&gt;core_new.2436
  File: core_new.2436
  Size: 3114838104      Blocks: 1528400    IO Block: 4096   regular file
ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;bc &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;(1528400 * 512)/1024/1024&apos;&lt;/span&gt;
746
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Why is Core Dump file a spare file? Core dump is a dump of the virtual memory space, but process usually do not use the entire virtual space. There are unmapped space ranges for two purposes.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Reserved but unmapped space.&lt;/li&gt;
  &lt;li&gt;Gaps between different segments (e.g. stack, heap) are never mapped.&lt;/li&gt;
  &lt;li&gt;Memory fragmentation.&lt;/li&gt;
  &lt;li&gt;Modern 64-bit systems have enormous theoretical address spaces. A process would not use all of them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GDB understands the sparse Core Dump. Although Core Dump is often sparse, it is not always guaranteed.&lt;/p&gt;

&lt;h1 id=&quot;quickstart&quot;&gt;Quickstart&lt;/h1&gt;

&lt;p&gt;Command &lt;em&gt;gdb&lt;/em&gt; is an interactive Shell capable of inspecting execution details of a process at a certain point, like dereferencing an uninitialized or NULL pointer (address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;With the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--nx&lt;/code&gt;, &lt;em&gt;gdb&lt;/em&gt; skips the &lt;a href=&quot;#configuration&quot;&gt;configuration&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb &lt;span class=&quot;nt&quot;&gt;--nx&lt;/span&gt;
GNU gdb &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Ubuntu 12.1-0ubuntu1~22.04.2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 12.1
Copyright &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later &amp;lt;http://gnu.org/licenses/gpl.html&amp;gt;
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type &lt;span class=&quot;s2&quot;&gt;&quot;show copying&quot;&lt;/span&gt; and &lt;span class=&quot;s2&quot;&gt;&quot;show warranty&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;details.
This GDB was configured as &lt;span class=&quot;s2&quot;&gt;&quot;x86_64-linux-gnu&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Type &lt;span class=&quot;s2&quot;&gt;&quot;show configuration&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;configuration details.
For bug reporting instructions, please see:
&amp;lt;https://www.gnu.org/software/gdb/bugs/&amp;gt;.
Find the GDB manual and other documentation resources online at:
    &amp;lt;http://www.gnu.org/software/gdb/documentation/&amp;gt;.

For &lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt;, &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;help&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Type &lt;span class=&quot;s2&quot;&gt;&quot;apropos word&quot;&lt;/span&gt; to search &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;commands related to &lt;span class=&quot;s2&quot;&gt;&quot;word&quot;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this section, we will describe multiple ways to make use of the GDB.&lt;/p&gt;

&lt;h2 id=&quot;launch-a-process&quot;&gt;Launch a Process&lt;/h2&gt;

&lt;p&gt;With the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--args&lt;/code&gt;, you can pass to the program arguments at the end of command line.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; /path/to/program &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;arglist]

&lt;span class=&quot;c&quot;&gt;# -or- interactively&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; file /path/to/program
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; run &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;arglist]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;trace-a-process&quot;&gt;Trace a Process&lt;/h2&gt;

&lt;p&gt;With the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt;, you can omit the binary. We can &lt;a href=&quot;#core-dump&quot;&gt;generate a Core Dump file&lt;/a&gt; on the fly with &lt;em&gt;gcore&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# with binary&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb /path/to/program &amp;lt;pid&amp;gt;

&lt;span class=&quot;c&quot;&gt;# no binary; must have &apos;-p&apos;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; pid

&lt;span class=&quot;c&quot;&gt;# generate core dump&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;help &lt;/span&gt;gcore
generate-core-file, gcore
Save a core file with the current state of the debugged process.
Usage: generate-core-file &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;FILENAME]
Argument is optional filename.  Default filename is &lt;span class=&quot;s1&quot;&gt;&apos;core.PROCESS_ID&apos;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; gcore
warning: Memory &lt;span class=&quot;nb&quot;&gt;read &lt;/span&gt;failed &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;corefile section, 4096 bytes at 0xffffffffff600000.
Saved corefile core.1231557

&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; shell &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-lhs&lt;/span&gt; core.1231557
9.9M &lt;span class=&quot;nt&quot;&gt;-rw-rw-r--&lt;/span&gt; 1 ubuntu ubuntu 9.9M Aug 15 14:15 core.1231557
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;load-a-core-dump&quot;&gt;Load a Core Dump&lt;/h2&gt;

&lt;p&gt;With the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-c&lt;/code&gt;, you can omit the binary.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# binary available&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb /path/to/program /path/to/core.pid

&lt;span class=&quot;c&quot;&gt;# no binary; must have &apos;-c&apos;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gdb &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; /path/to/core.pid

&lt;span class=&quot;c&quot;&gt;# -or- interactively&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; file /path/to/program
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;gdb&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; core-file /path/to/core.pid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;gdb-commands&quot;&gt;GDB Commands&lt;/h1&gt;

&lt;p&gt;At any moment, we can type the special command &lt;em&gt;help&lt;/em&gt; for help.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) help

(gdb) help internals

(gdb) help disassemble
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The following is a list of commonly used interactive GDB commands.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Keyboard ENTER key repeats the last command.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;run&lt;/em&gt; starts or restart the program. The argument list can be provided immediately like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run -a -x y&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;A program either runs successfully, or runs into issues. When the program is running in the middle, we can stop it via shortcut &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-C&lt;/code&gt; or gdb command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signal SIGINT&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;backtrace&lt;/em&gt; shows the call stack. With the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-full&lt;/code&gt;, it also prints local variables.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) backtrace
#0  0x0000ffffa7a7bd74 in __GI_epoll_pwait (epfd=32, events=0xaaab04fa8760, maxevents=512, timeout=492, set=0x0) at ../sysdeps/unix/sysv/linux/epoll_pwait.c:40
#1  0x0000aaaadbfe4ac0 in ngx_epoll_process_events (cycle=0xaaab04fa10e0, timer=492, flags=1) at src/event/modules/ngx_epoll_module.c:800
#2  0x0000aaaadbfcf65c in ngx_process_events_and_timers (cycle=0xaaab04fa10e0) at src/event/ngx_event.c:258
#3  0x0000aaaadbfe10b4 in ngx_worker_process_cycle (cycle=0xaaab04fa10e0, data=0x0) at src/os/unix/ngx_process_cycle.c:793
#4  0x0000aaaadbfdccb8 in ngx_spawn_process (cycle=0xaaab04fa10e0, proc=0xaaaadbfe0fc8 &amp;lt;ngx_worker_process_cycle&amp;gt;, data=0x0, name=0xaaaadc2ba400 &quot;worker process&quot;, respawn=-3) at src/os/unix/ngx_process.c:199
#5  0x0000aaaadbfdfa98 in ngx_start_worker_processes (cycle=0xaaab04fa10e0, n=1, type=-3) at src/os/unix/ngx_process_cycle.c:382
#6  0x0000aaaadbfdefc4 in ngx_master_process_cycle (cycle=0xaaab04fa10e0) at src/os/unix/ngx_process_cycle.c:135
#7  0x0000aaaadbf91b2c in main (argc=5, argv=0xffffd729e868) at src/core/nginx.c:387
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;a href=&quot;#pwndbg&quot;&gt;pwndbg&lt;/a&gt; has a more powerful &lt;em&gt;context&lt;/em&gt; command to show more information.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;frame&lt;/em&gt;. Stack Frame is an important concept in GDB. It represents a function call and occupies an entry in the call stack.&lt;/p&gt;

    &lt;p&gt;Take the output from step 3 for example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#0&lt;/code&gt; is the innermost frame (most recent function), while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#7&lt;/code&gt; is the outermost frame (the &lt;em&gt;main&lt;/em&gt; function). We call the frame &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#0&lt;/code&gt; the current frame. It is the base of a lot of GDB commands.&lt;/p&gt;

    &lt;p&gt;A frame contains the function name, arguments, local variables, source code line, etc. Specially, it includes the memory address at which the function is executing, namely the address where the code is mapped onto, recorded in the register &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$pc&lt;/code&gt;. Please be noted that, it is not the stack address.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;frame N           # Select frame number N
up                # Move to the caller frame (up the call stack)
down              # Move to the callee frame (down the call stack)

info frame       # Show detailed info about current frame
info locals      # Show local variables in current frame
info args        # Show function arguments of current frame
   
print var        # Print value of variable in current frame
set var=value    # Set value of variable in current frame
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/gdb-frame.png&quot; alt=&quot;gdb-frame.png&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;disassemble&lt;/em&gt; shows the assembly code. By default, it shows the code surrounding the register &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$pc&lt;/code&gt;, namely the current frame. With the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/s&lt;/code&gt;, it also shows the source code.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) disassemble /s 0x0000aaaadbfe4ac0
Dump of assembler code for function ngx_epoll_process_events:
src/event/modules/ngx_epoll_module.c:
785     {
   0x0000aaaadbfe4a38 &amp;lt;+0&amp;gt;:     stp     x29, x30, [sp, #-128]!
   0x0000aaaadbfe4a3c &amp;lt;+4&amp;gt;:     mov     x29, sp
   0x0000aaaadbfe4a40 &amp;lt;+8&amp;gt;:     str     x0, [sp, #40]
   0x0000aaaadbfe4a44 &amp;lt;+12&amp;gt;:    str     x1, [sp, #32]
   0x0000aaaadbfe4a48 &amp;lt;+16&amp;gt;:    str     x2, [sp, #24]
   
786         int                events;
787         uint32_t           revents;
788         ngx_int_t          instance, i;
789         ngx_uint_t         level;
790         ngx_err_t          err;
791         ngx_event_t       *rev, *wev;
792         ngx_queue_t       *queue;
793         ngx_connection_t  *c;
794
795         /* NGX_TIMER_INFINITE == INFTIM */
796
797         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle-&amp;gt;log, 0,
   0x0000aaaadbfe4a4c &amp;lt;+20&amp;gt;:    ldr     x0, [sp, #40]
   0x0000aaaadbfe4a50 &amp;lt;+24&amp;gt;:    ldr     x0, [x0, #16]
   0x0000aaaadbfe4a54 &amp;lt;+28&amp;gt;:    ldr     x0, [x0]
   0x0000aaaadbfe4a58 &amp;lt;+32&amp;gt;:    bl      0xaaaadc195650 &amp;lt;ngx_http_lua_kong_get_dynamic_log_level&amp;gt;
--Type &amp;lt;RET&amp;gt; for more, q to quit, c to continue without paging--
   0x0000aaaadbfe4a5c &amp;lt;+36&amp;gt;:    and     x0, x0, #0x80
   0x0000aaaadbfe4a60 &amp;lt;+40&amp;gt;:    cmp     x0, #0x0
   0x0000aaaadbfe4a64 &amp;lt;+44&amp;gt;:    b.eq    0xaaaadbfe4a88 &amp;lt;ngx_epoll_process_events+80&amp;gt;  // b.none
   0x0000aaaadbfe4a68 &amp;lt;+48&amp;gt;:    ldr     x0, [sp, #40]
   0x0000aaaadbfe4a6c &amp;lt;+52&amp;gt;:    ldr     x1, [x0, #16]
   0x0000aaaadbfe4a70 &amp;lt;+56&amp;gt;:    ldr     x4, [sp, #32]
   0x0000aaaadbfe4a74 &amp;lt;+60&amp;gt;:    adrp    x0, 0xaaaadc2ba000
   0x0000aaaadbfe4a78 &amp;lt;+64&amp;gt;:    add     x3, x0, #0xac0
   0x0000aaaadbfe4a7c &amp;lt;+68&amp;gt;:    mov     w2, #0x0                        // #0
   0x0000aaaadbfe4a80 &amp;lt;+72&amp;gt;:    mov     x0, #0x8                        // #8
   0x0000aaaadbfe4a84 &amp;lt;+76&amp;gt;:    bl      0xaaaadbf946fc &amp;lt;ngx_log_error_core&amp;gt;
   
798                        &quot;epoll timer: %M&quot;, timer);
799
800         events = epoll_wait(ep, event_list, (int) nevents, timer);
   0x0000aaaadbfe4a88 &amp;lt;+80&amp;gt;:    adrp    x0, 0xaaaadc661000 &amp;lt;week+16&amp;gt;
   0x0000aaaadbfe4a8c &amp;lt;+84&amp;gt;:    add     x0, x0, #0xb90
   0x0000aaaadbfe4a90 &amp;lt;+88&amp;gt;:    ldr     w4, [x0]
   0x0000aaaadbfe4a94 &amp;lt;+92&amp;gt;:    adrp    x0, 0xaaaadc6a0000 &amp;lt;ngx_processes+47632&amp;gt;
   0x0000aaaadbfe4a98 &amp;lt;+96&amp;gt;:    add     x0, x0, #0xa48
   0x0000aaaadbfe4a9c &amp;lt;+100&amp;gt;:   ldr     x1, [x0]
   0x0000aaaadbfe4aa0 &amp;lt;+104&amp;gt;:   adrp    x0, 0xaaaadc6a0000 &amp;lt;ngx_processes+47632&amp;gt;
   0x0000aaaadbfe4aa4 &amp;lt;+108&amp;gt;:   add     x0, x0, #0xa50
   0x0000aaaadbfe4aa8 &amp;lt;+112&amp;gt;:   ldr     x0, [x0]
   0x0000aaaadbfe4aac &amp;lt;+116&amp;gt;:   mov     w2, w0
--Type &amp;lt;RET&amp;gt; for more, q to quit, c to continue without paging--q
Quit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The &lt;a href=&quot;#objdump&quot;&gt;objdump&lt;/a&gt; has similar capabilities.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;list&lt;/em&gt; shows only source code. With the argument &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt;, it shows code surrounding the current frame.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  frame 1
#1  0x0000aaaaad984ac0 in ngx_epoll_process_events (cycle=0xaaaab6b09130, timer=0x134, flags=0x1) at src/event/modules/ngx_epoll_module.c:800
800         events = epoll_wait(ep, event_list, (int) nevents, timer);
gef➤  list .
795         /* NGX_TIMER_INFINITE == INFTIM */
796
797         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle-&amp;gt;log, 0,
798                        &quot;epoll timer: %M&quot;, timer);
799
800         events = epoll_wait(ep, event_list, (int) nevents, timer);
801
802         err = (events == -1) ? ngx_errno : 0;
803
804         if (flags &amp;amp; NGX_UPDATE_TIME || ngx_event_timer_alarm) {
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;To show the source code pathname.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) info sources
/home/kong/.cache/bazel/_bazel_kong/ee741459d483c56c5059256f49a7a414/execroot/_main/bazel-out/aarch64-fastbuild/bin/build/kong-dev/openresty/nginx/sbin/nginx:
(Full debug information has not yet been read for this file.)
   
/home/kong/.cache/bazel/_bazel_kong/ee741459d483c56c5059256f49a7a414/execroot/_main/bazel-out/aarch64-fastbuild/bin/external/openresty/openresty.build_tmpdir/build/nginx-1.25.3/src/core/nginx.c,
/home/kong/.cache/bazel/_bazel_kong/ee741459d483c56c5059256f49a7a414/execroot/_main/bazel-out/aarch64-fastbuild/bin/external/openresty/openresty.build_tmpdir/build/nginx-1.25.3/src/os/unix/ngx_files.h,
/home/kong/.cache/bazel/_bazel_kong/ee741459d483c56c5059256f49a7a414/execroot/_main/bazel-out/aarch64-fastbuild/bin/external/openresty/openresty.build_tmpdir/build/nginx-1.25.3/src/core/ngx_log.h,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;break&lt;/em&gt; toggle a breakpoint and pauses the program at the specified line.&lt;/p&gt;

    &lt;p&gt;Use &lt;em&gt;list&lt;/em&gt; or &lt;em&gt;disassemble&lt;/em&gt; to identify the code line you are interested in.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) break ngx_epoll_module.c:800
Breakpoint 2 at 0xaaaadbfe4a88: file src/event/modules/ngx_epoll_module.c, line 800.
(gdb) info breakpoints
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x0000aaaadbfe4a88 in ngx_epoll_process_events at src/event/modules/ngx_epoll_module.c:800
(gdb) delete breakpoints 2
(gdb) info breakpoints
No breakpoints, watchpoints, tracepoints, or catchpoints.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;You can define a &lt;em&gt;conditional&lt;/em&gt; breakpoint like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;break 15 if var &amp;gt; 10&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;watch&lt;/em&gt; monitors a variable and pauses the program when the variable is modified.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) info variables -t ngx_cycle_t
All defined variables with type matching regular expression &quot;ngx_cycle_t&quot; :
   
File ../echo-nginx-module-0.63/src/ngx_http_echo_filter.c:
28:     static volatile ngx_cycle_t *ngx_http_echo_prev_cycle;
   
File ../headers-more-nginx-module-0.37/src/ngx_http_headers_more_filter_module.c:
111:    static volatile ngx_cycle_t *ngx_http_headers_more_prev_cycle;
   
File ../ngx_lua-0.10.26/src/ngx_http_lua_module.c:
71:     static volatile ngx_cycle_t *ngx_http_lua_prev_cycle;
   
File src/core/ngx_cycle.c:
21:     volatile ngx_cycle_t *ngx_cycle;
   
File src/os/unix/ngx_process_cycle.c:
73:     static ngx_cycle_t ngx_exit_cycle;
   
(gdb) watch ngx_cycle
Hardware watchpoint 5: ngx_cycle
   
(gdb) info watchpoints
Num     Type           Disp Enb Address            What
5       hw watchpoint  keep y                      ngx_cycle
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;continue&lt;/em&gt; resumes the program until crash, the next breakpoint or exit.
    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;next&lt;/em&gt; executes the next statement.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;em&gt;step&lt;/em&gt; steps into funtion call while &lt;em&gt;next&lt;/em&gt; does not.&lt;/p&gt;

        &lt;p&gt;&lt;em&gt;stepi&lt;/em&gt; steps over machine instruction instead of source code statement.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;em&gt;finish&lt;/em&gt; completes the current function call and then pause.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;print&lt;/em&gt; shows values of variables.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) print ngx_cycle
$12 = (volatile ngx_cycle_t *) 0xaaab04fa10e0
    
(gdb) print * $12
$13 = {conf_ctx = 0xaaab04fa2580, pool = 0xaaab04fa10a0, log = 0xaaab04fa10f8, new_log = {log_level = 6, file = 0xaaab04fa15f0, connection = 0, disk_full_time = 0, handler = 0x0, data = 0x0, writer = 0x0, wdata = 0x0, action = 0x0, next = 0x0}, log_use_stderr = 0,
  files = 0x0, free_connections = 0xffff705cbb78, free_connection_n = 15840, modules = 0xaaab04fa2cb0, modules_n = 89, modules_used = 1, reusable_connections_queue = {prev = 0xaaab04fa1180, next = 0xaaab04fa1180}, reusable_connections_n = 0, connections_reuse_time = 0,
  listening = {elts = 0xaaab055dbf30, nelts = 16, size = 296, nalloc = 20, pool = 0xaaab04fa10a0, old_elts = 0xaaab055d45d0}, paths = {elts = 0xaaab04fa1530, nelts = 5, size = 8, nalloc = 10, pool = 0xaaab04fa10a0, old_elts = 0x0}, config_dump = {elts = 0xaaab04ffdd40,
    nelts = 7, size = 24, nalloc = 8, pool = 0xaaab04fa10a0, old_elts = 0xaaab04ffde30}, config_dump_rbtree = {root = 0xaaab04fc3850, sentinel = 0xaaab04fa1248, insert = 0xaaaadbfa0258 &amp;lt;ngx_str_rbtree_insert_value&amp;gt;}, config_dump_sentinel = {key = 0, left = 0x0,
    right = 0x0, parent = 0x0, color = 0 &apos;\000&apos;, data = 0 &apos;\000&apos;}, open_files = {last = 0xaaab04fa1278, part = {elts = 0xaaab04fa15f0, nelts = 7, next = 0x0}, size = 40, nalloc = 20, pool = 0xaaab04fa10a0}, shared_memory = {last = 0xaaab051b0240, part = {
      elts = 0xaaab04fa1940, nelts = 1, next = 0xaaab04fc4a60}, size = 88, nalloc = 1, pool = 0xaaab04fa10a0}, connection_n = 16384, files_n = 0, connections = 0xffff7057f010, read_events = 0xffff703fe010, write_events = 0xffff7027d010, old_cycle = 0x0, conf_file = {
    len = 58, data = 0xaaab04fa1480 &quot;/kong-ee/bazel-bin/build/kong-dev/kong/servroot/nginx.conf&quot;}, conf_param = {len = 0, data = 0xaaab04fa14f0 &quot;&quot;}, conf_prefix = {len = 48, data = 0xaaab04fa13a0 &quot;/kong-ee/bazel-bin/build/kong-dev/kong/servroot/&quot;}, prefix = {len = 48,
    data = 0xaaab04fa13e0 &quot;/kong-ee/bazel-bin/build/kong-dev/kong/servroot/&quot;}, error_log = {len = 14, data = 0xaaab04fa1440 &quot;logs/error.log&quot;}, lock_file = {len = 64, data = 0xaaab055b4330 &quot;/kong-ee/bazel-bin/build/kong-dev/kong/servroot/logs/nginx.lock.accept&quot;},
  hostname = {len = 7, data = 0xaaab04fa2c70 &quot;kong-ee&quot;}, intercept_error_log_handler = 0x0, intercept_error_log_data = 0x0, entered_logger = 0}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;x&lt;/em&gt; shows values referenced by an memory address.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0x0000ffffe2a53890│+0x0000: 0x0000ffffe2a538d0  →  0x0000ffffe2a53950  →  0x0000ffffe2a539a0  →  0x0000ffffe2a539d0  →  0x0000ffffe2a53a40  →  0x0000ffffe2a53a80  →  0x0000ffffe2a53b90         ← $x29, $sp
0x0000ffffe2a53898│+0x0008: 0x0000aaaaad984ac0  →  &amp;lt;ngx_epoll_process_events+0088&amp;gt; str w0,  [sp,  #64]
0x0000ffffe2a538a0│+0x0010: 0x0000ffffe2a54028  →  0x0000ffffe2a54dcf  →  &quot;nginx: worker process&quot;
0x0000ffffe2a538a8│+0x0018: 0x0000000000000005
0x0000ffffe2a538b0│+0x0020: 0x0000aaaaadffde88  →  0x0000aaaaad931400  →  &amp;lt;__do_global_dtors_aux+0000&amp;gt; stp x29,  x30,  [sp,  #-32]!
0x0000ffffe2a538b8│+0x0028: 0x0000aaaaad931574  →  &amp;lt;main+0000&amp;gt; sub sp,  sp,  #0x320
 
gef➤  x/a 0x0000ffffe2a538a0
0xffffe2a538a0: 0xffffe2a54028
gef➤  x/a 0xffffe2a54028
0xffffe2a54028: 0xffffe2a54dcf
 
gef➤  x/s 0xffffe2a54dcf
0xffffe2a54dcf: &quot;nginx: worker process&quot;
 
gef➤  print (char *) 0x0000ffffe2a54dcf
$5 = 0xffffe2a54dcf &quot;nginx: worker process&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;info&lt;/em&gt; is very useful.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;record&lt;/em&gt; combined with *reverse-&lt;cmd&gt;* (e.g. *reverse-step*) can execute the program in reverse order. Therefore, there is no need to re-run the program to inpsect previous execution contexts.&lt;/cmd&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;shell&lt;/em&gt; invokes a shell command, like &lt;em&gt;shell ll&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Similar to Bash, you can check historical GDB commands in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gdb_history&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For sophiscated manual, please refer to &lt;a href=&quot;https://www.sourceware.org/gdb/documentation/&quot;&gt;the official documentation&lt;/a&gt;. It you are using &lt;a href=&quot;#pwndgb&quot;&gt;pwndgb&lt;/a&gt;, refer to &lt;a href=&quot;https://drive.google.com/file/d/16t9MV8KTFXK7oX_CzXhmDdaVnjT8IYM4/view&quot;&gt;cheatsheet&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;more-tools&quot;&gt;More Tools&lt;/h1&gt;

&lt;p&gt;Apart from GDB, we have a bunch of other tools to inspect objects.&lt;/p&gt;

&lt;p&gt;To make it simple, we can even use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt; to inspect the file.&lt;/p&gt;

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

&lt;p&gt;hexdump can dump file contents in various formats (e.g. hexadecimal), including customized format with the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--format&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following example dumps the contents in ASCII format.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;hexdump &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; core.pid | less 

000140b0  f0 b8 1d 00 00 00 00 00  0a 00 00 00 00 00 00 00  |................|
000140c0  00 5f 49 54 4d 5f 64 65  72 65 67 69 73 74 65 72  |._ITM_deregister|
000140d0  54 4d 43 6c 6f 6e 65 54  61 62 6c 65 00 5f 5f 67  |TMCloneTable.__g|
000140e0  6d 6f 6e 5f 73 74 61 72  74 5f 5f 00 5f 49 54 4d  |mon_start__._ITM|
000140f0  5f 72 65 67 69 73 74 65  72 54 4d 43 6c 6f 6e 65  |_registerTMClone|
00014100  54 61 62 6c 65 00 63 72  79 70 74 5f 72 00 6c 75  |Table.crypt_r.lu|
00014110  61 5f 70 75 73 68 66 73  74 72 69 6e 67 00 6c 75  |a_pushfstring.lu|
00014120  61 5f 73 65 74 65 78 64  61 74 61 00 6c 75 61 5f  |a_setexdata.lua_|
00014130  67 65 74 66 69 65 6c 64  00 6c 75 61 4c 5f 70 75  |getfield.luaL_pu|
00014140  73 68 72 65 73 75 6c 74  00 6c 75 61 5f 78 6d 6f  |shresult.lua_xmo|
00014150  76 65 00 6c 75 61 5f 72  65 73 75 6d 65 00 6c 75  |ve.lua_resume.lu|
00014160  61 4c 5f 61 64 64 6c 73  74 72 69 6e 67 00 6c 75  |aL_addlstring.lu|
00014170  61 4c 5f 6f 70 74 6e 75  6d 62 65 72 00 6c 75 61  |aL_optnumber.lua|
00014180  5f 6e 65 77 75 73 65 72  64 61 74 61 00 6c 75 61  |_newuserdata.lua|
00014190  5f 73 65 74 66 69 65 6c  64 00 6c 75 61 5f 73 65  |_setfield.lua_se|
000141a0  74 74 6f 70 00 6c 75 61  5f 70 75 73 68 73 74 72  |ttop.lua_pushstr|
000141b0  69 6e 67 00 6c 75 61 6f  70 65 6e 5f 66 66 69 00  |ing.luaopen_ffi.|
000141c0  6c 75 61 5f 67 65 74 69  6e 66 6f 00 6c 75 61 5f  |lua_getinfo.lua_|
000141d0  69 73 6e 75 6d 62 65 72  00 6c 75 61 4c 5f 63 68  |isnumber.luaL_ch|
000141e0  65 63 6b 6c 73 74 72 69  6e 67 00 6c 75 61 5f 6e  |ecklstring.lua_n|
000141f0  65 78 74 00 6c 75 61 5f  74 6f 74 68 72 65 61 64  |ext.lua_tothread|
00014200  00 6c 75 61 5f 67 63 00  6c 75 61 5f 63 72 65 61  |.lua_gc.lua_crea|
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, all the non-printable characters are shown as dots in the ASCII column.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; i&amp;lt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;255&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; ++i&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; %x &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt; | hexdump &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt;
00000000  00 01 02 03 04 05 06 07  08 09 0a 0b 0c 0d 0e 0f  |................|
00000010  10 11 12 13 14 15 16 17  18 19 1a 1b 1c 1d 1e 1f  |................|
00000020  20 21 22 23 24 25 26 27  28 29 2a 2b 2c 2d 2e 2f  | &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;#&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$%&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;amp;&apos;()*+,-./|
00000030  30 31 32 33 34 35 36 37  38 39 3a 3b 3c 3d 3e 3f  |0123456789:;&amp;lt;=&amp;gt;?|
00000040  40 41 42 43 44 45 46 47  48 49 4a 4b 4c 4d 4e 4f  |@ABCDEFGHIJKLMNO|
00000050  50 51 52 53 54 55 56 57  58 59 5a 5b 5c 5d 5e 5f  |PQRSTUVWXYZ[&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\]&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^_|
00000060  60 61 62 63 64 65 66 67  68 69 6a 6b 6c 6d 6e 6f  |&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;abcdefghijklmno|
00000070  70 71 72 73 74 75 76 77  78 79 7a 7b 7c 7d 7e 7f  |pqrstuvwxyz&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;|&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;~.|
00000080  80 81 82 83 84 85 86 87  88 89 8a 8b 8c 8d 8e 8f  |................|
00000090  90 91 92 93 94 95 96 97  98 99 9a 9b 9c 9d 9e 9f  |................|
000000a0  a0 a1 a2 a3 a4 a5 a6 a7  a8 a9 aa ab ac ad ae af  |................|
000000b0  b0 b1 b2 b3 b4 b5 b6 b7  b8 b9 ba bb bc bd be bf  |................|
000000c0  c0 c1 c2 c3 c4 c5 c6 c7  c8 c9 ca cb cc &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;ce cf  |................|
000000d0  d0 d1 d2 d3 d4 d5 d6 d7  d8 d9 da db dc &lt;span class=&quot;nb&quot;&gt;dd &lt;/span&gt;de &lt;span class=&quot;nb&quot;&gt;df&lt;/span&gt;  |................|
000000e0  e0 e1 e2 e3 e4 e5 e6 e7  e8 e9 ea eb ec ed ee ef  |................|
000000f0  f0 f1 f2 f3 f4 f5 f6 f7  f8 f9 fa fb &lt;span class=&quot;nb&quot;&gt;fc &lt;/span&gt;fd fe ff  |................|
00000100
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The following examples show that the object contains a lot of zeros.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;hexdump &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; 0x577af3685000-0x577af8547000.bin | less
00003b90  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00003ba0  00 00 00 00 00 00 00 00  91 00 00 00 00 00 00 00  |................|
00003bb0  30 8c 68 f3 7a 57 00 00  30 8c 68 f3 7a 57 00 00  |0.h.zW..0.h.zW..|
00003bc0  a0 8c 68 f3 7a 57 00 00  06 00 00 00 00 00 00 00  |..h.zW..........|
00003bd0  31 37 32 2e 31 36 2e 30  2e 31 30 3a 35 33 00 00  |172.16.0.10:53..|
00003be0  00 00 00 00 00 00 00 00  98 8a 68 f3 7a 57 00 00  |..........h.zW..|
00003bf0  40 8c 68 f3 7a 57 00 00  00 00 00 00 00 00 00 00  |@.h.zW..........|
00003c00  40 72 9b 6b 0b 73 00 00  40 8b 68 f3 7a 57 00 00  |@r.k.s..@.h.zW..|
00003c10  31 37 32 2e 31 36 2e 30  2e 31 30 00 00 00 00 00  |172.16.0.10.....|
00003c20  02 00 00 35 ac 10 00 0a  00 00 00 00 00 00 00 00  |...5............|
00003c30  00 00 00 00 00 00 00 00  61 00 00 00 00 00 00 00  |........a.......|
00003c40  0e 00 00 00 00 00 00 00  d0 8b 68 f3 7a 57 00 00  |..........h.zW..|
00003c50  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00003c60  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00003c70  88 8b 68 f3 7a 57 00 00  10 00 00 00 00 00 00 00  |..h.zW..........|
00003c80  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00003c90  00 00 00 00 00 00 00 00  91 00 00 00 00 00 00 00  |................|
00003ca0  20 8d 68 f3 7a 57 00 00  20 8d 68 f3 7a 57 00 00  | .h.zW.. .h.zW..|
00003cb0  90 8d 68 f3 7a 57 00 00  06 00 00 00 00 00 00 00  |..h.zW..........|
00003cc0  20 8c 68 f3 7a 57 00 00  10 00 00 00 00 00 00 00  | .h.zW..........|
00003cd0  0e 00 00 00 00 00 00 00  e0 8c 68 f3 7a 57 00 00  |..........h.zW..|
00003ce0  31 37 32 2e 31 36 2e 30  2e 31 30 3a 35 33 00 00  |172.16.0.10:53..|
00003cf0  00 00 00 00 00 00 00 00  e8 8b 68 f3 7a 57 00 00  |..........h.zW..|
00003d00  30 8d 68 f3 7a 57 00 00  00 00 00 00 00 00 00 00  |0.h.zW..........|
00003d10  f8 31 98 69 0b 73 00 00  f8 8b 68 f3 7a 57 00 00  |.1.i.s....h.zW..|
00003d20  00 00 00 00 00 00 00 00  61 00 00 00 00 00 00 00  |........a.......|
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;p&gt;Though &lt;a href=&quot;#hexdump&quot;&gt;hexdump&lt;/a&gt; shows ASCII characters, it is not easy to extract the ASCII column. GNU &lt;em&gt;strings&lt;/em&gt;, on the other hand, can dump &lt;em&gt;printable&lt;/em&gt; characters and helps identify large strings in the Core Dump.&lt;/p&gt;

&lt;p&gt;The option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; prefixes the string with the offset in the object file. It is useful show the distribution and density of string.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;strings &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; d /path/to/core.pid &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; core.pid.density

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;strings &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; 4] /path/to/core.pid &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; core.pid.ascii

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; core.pid.ascii.sorted core.pid.ascii

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uniq&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; core.pid.ascii.sorted &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; core.pid.ascii.sorted.uniq

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-nrk1&lt;/span&gt;,1 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; core.pid.ascii.sorted.uniq.sorted core.pid.ascii.sorted.uniq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, non-printable characters are not included in the output.&lt;/p&gt;

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

&lt;p&gt;readelf is the &lt;a href=&quot;https://stackoverflow.com/a/8979687&quot;&gt;architecture independent&lt;/a&gt; but &lt;a href=&quot;#objdump&quot;&gt;objdump&lt;/a&gt; can dump source code.&lt;/p&gt;

&lt;p&gt;Specially, gef supports print ELF info.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gef➤  elf-info
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Regarding more examples of readelf, please see &quot;biji&quot;.&lt;/p&gt;

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

&lt;p&gt;&lt;a href=&quot;#readelf&quot;&gt;readelf&lt;/a&gt; cannot dump source code as objdump does. Here is an example.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;objdump &lt;span class=&quot;nt&quot;&gt;--source&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--source-comment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;txt test-gdb.out

...

0000000000001149 &amp;lt;f&amp;gt;:
txt#include &amp;lt;stdio.h&amp;gt;
txt
txtint f&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;int a, int b&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
txt&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    1149:       f3 0f 1e fa             endbr64
txt     int &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
txt     &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; a + b&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    114d:       8d 04 37                lea    &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;%rdi,%rsi,1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;,%eax
txt     &lt;span class=&quot;k&quot;&gt;return &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
txt&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    1150:       c3                      ret

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

&lt;p&gt;&lt;a href=&quot;#gdb-commands&quot;&gt;GDB command disassemble and list&lt;/a&gt; can also dump source code and assembler code.&lt;/p&gt;

&lt;h1 id=&quot;memory&quot;&gt;Memory&lt;/h1&gt;

&lt;p&gt;We can make use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;top&lt;/code&gt; to show the general memory utilization.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;top &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; +RES &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;pgrep &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;,&apos;&lt;/span&gt; nginx&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

Tasks:   2 total,   0 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:  0.9 us,  1.8 sy,  0.0 ni, 97.3 &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7841.2 total,   1885.2 free,   4823.7 used,   1392.9 buff/cache
MiB Swap:   1024.0 total,    105.4 free,    918.6 used.   3017.5 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
37937 kong      20   0 1393704 414628  11904 S   0.0   5.2  14:36.72 nginx
37936 kong      20   0 1023736 108848    896 S   0.0   1.4   0:00.00 nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Memory mappings represents how virtual memory space is mapped to RAM. It tells us how the memory is used. GDB and gef both can show memory mappings. Of the three commands below, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maintenance info sections&lt;/code&gt; only show the mappings of different memory sections of the ELF. It corresponds to only a few starting lines of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vmmap&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;info proc mappings&lt;/code&gt; that include dyanmically allocated memory (e.g. heap/stack).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) maintenance info sections

gef➤  vmmap

(gdb) info proc mappings
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Without GDB, we can show the memory mappings of a running process with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pmap&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pmap &lt;span class=&quot;nt&quot;&gt;-X&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;pgrep nginx&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; all-&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Iseconds&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;.pmap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Core dumps captured at different timestamps reveal newly allocated chunks. Moreover, we can use &lt;a href=&quot;#hexdump&quot;&gt;hexdump&lt;/a&gt;, &lt;a href=&quot;#strings&quot;&gt;strings&lt;/a&gt; and even the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim&lt;/code&gt; to see what is inside the new chunks. How to identify newly allocated chunks?&lt;/p&gt;

&lt;p&gt;The following are two excerpts from two Core Dumps. We will use this data as an example to show the process.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Core Dump 1
[14]      0x577ae51df000-&amp;gt;0x577ae521a000 at 0x00002a40: load1 ALLOC LOAD READONLY HAS_CONTENTS
[15]      0x577ae54fc000-&amp;gt;0x577ae54ff000 at 0x0003da40: load2 ALLOC LOAD READONLY HAS_CONTENTS
[16]      0x577ae54ff000-&amp;gt;0x577ae551e000 at 0x00040a40: load3 ALLOC LOAD HAS_CONTENTS
[17]      0x577ae551e000-&amp;gt;0x577ae5550000 at 0x0005fa40: load4 ALLOC LOAD HAS_CONTENTS
[18]      0x577ae63cd000-&amp;gt;0x577ae66a0000 at 0x00091a40: load5 ALLOC LOAD HAS_CONTENTS
[19]      0x577ae66a0000-&amp;gt;0x577af3685000 at 0x00364a40: load6 ALLOC LOAD HAS_CONTENTS
[20]      0x730b65ac0000-&amp;gt;0x730b671c1000 at 0x0d349a40: load7 ALLOC LOAD HAS_CONTENTS

# Core Dump 2
[14]      0x577ae51df000-&amp;gt;0x577ae521a000 at 0x00002a78: load1 ALLOC LOAD READONLY HAS_CONTENTS
[15]      0x577ae54fc000-&amp;gt;0x577ae54ff000 at 0x0003da78: load2 ALLOC LOAD READONLY HAS_CONTENTS
[16]      0x577ae54ff000-&amp;gt;0x577ae551e000 at 0x00040a78: load3 ALLOC LOAD HAS_CONTENTS
[17]      0x577ae551e000-&amp;gt;0x577ae5550000 at 0x0005fa78: load4 ALLOC LOAD HAS_CONTENTS
[18]      0x577ae63cd000-&amp;gt;0x577ae66a0000 at 0x00091a78: load5 ALLOC LOAD HAS_CONTENTS
[19]      0x577ae66a0000-&amp;gt;0x577af8547000 at 0x00364a78: load6 ALLOC LOAD HAS_CONTENTS
[20]      0x730b64d1d000-&amp;gt;0x730b671c1000 at 0x1220ba78: load7 ALLOC LOAD HAS_CONTENTS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The 19th mapping in Core Dump 2 has expanded its ending address than the Core Dump 1. We can calculate the increased size in bytes.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ $ bc &amp;lt;&amp;lt;&amp;lt; &apos;obase=16; ibase = 16; 0X577AF8547000 - 0X577AF3685000&apos;
4EC2000

~ $ bc &amp;lt;&amp;lt;&amp;lt; &apos;obase=10; ibase = 16; 0X577AF8547000 - 0X577AF3685000&apos;
82583552
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let us extract the newly allocated memory from Core Dump 2 and save to the local disk.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) dump memory ~/misc/0x577af3685000-0x577af8547000.bin 0x577af3685000 0x577af8547000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the extracted ranged memory dump, we can resort to &lt;a href=&quot;#more-tools&quot;&gt;More Tools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please check &quot;whatever&quot; and &quot;kong-dev&quot; for more details. You are strongly recommended to read &lt;a href=&quot;https://www.brendangregg.com/FlameGraphs/memoryflamegraphs.html&quot;&gt;Memory Leak (and Growth) Flame Graphs&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;nginx&quot;&gt;Nginx&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) p ngx_cycle-&amp;gt;pool
$1 = (ngx_pool_t *) 0x577ae63f3ff0
(gdb) p * ngx_cycle-&amp;gt;pool
$2 = {d = {last = 0x577ae63f7ff0 &quot;&quot;, end = 0x577ae63f7ff0 &quot;&quot;, next = 0x577ae63fd020, failed = 6}, max = 4095, current = 0x577ae643f5f0, chain = 0x0, large = 0x577ae64c52d8, cleanup = 0x577ae64c5980, log = 0x577ae63f4058}
(gdb)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;src/ngx_http_lua_socket_udp.c
 -&amp;gt; ngx_http_lua_socket_udp_setpeername
   -&amp;gt;     r = ngx_http_lua_get_req(L);
      -&amp;gt;     host.data = ngx_palloc(r-&amp;gt;pool, len + 1);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(gdb) p * (ngx_http_upstream_resolved_t *) 0x577af3685060
$4 = {host = {len = 3471771947605571377, data = 0x33353a30312e &amp;lt;error: Cannot access memory at address 0x33353a30312e&amp;gt;}, port = 0, no_port = 96185581326184, naddrs = 96185581326496, addrs = 0x0, sockaddr = 0x0, socklen = 97, name = {len = 14,
    data = 0x577af3685060 &quot;172.16.0.10:53&quot;}, ctx = 0x0}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;appendix&quot;&gt;Appendix&lt;/h1&gt;

&lt;p&gt;Copied from &lt;a href=&quot;ttps://jvns.ca/blog/2021/05/17/how-to-look-at-the-stack-in-gdb/&quot;&gt;How to look at the stack with gdb&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;stack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;heap_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Enter a string for the stack: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stack_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Enter a string for the heap: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;heap_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Stack string is: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stack_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Heap string is: %s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heap_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x is: %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>LuaRocks Tutorial</title>
   <link href="/2024/03/01/luarocks/"/>
   <updated>2024-03-01T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2024/03/01/luarocks</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#luarocks-luarocks&quot; id=&quot;markdown-toc-luarocks-luarocks&quot;&gt;LuaRocks luarocks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#manual-installation&quot; id=&quot;markdown-toc-manual-installation&quot;&gt;Manual Installation&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#build-lua&quot; id=&quot;markdown-toc-build-lua&quot;&gt;Build lua&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#build-luarocks&quot; id=&quot;markdown-toc-build-luarocks&quot;&gt;Build luarocks&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#rocks&quot; id=&quot;markdown-toc-rocks&quot;&gt;rocks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#rocks-servers&quot; id=&quot;markdown-toc-rocks-servers&quot;&gt;rocks servers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#config&quot; id=&quot;markdown-toc-config&quot;&gt;config&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#create-rocks&quot; id=&quot;markdown-toc-create-rocks&quot;&gt;Create Rocks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#upload-rocks&quot; id=&quot;markdown-toc-upload-rocks&quot;&gt;Upload Rocks&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#upload-to-official-server&quot; id=&quot;markdown-toc-upload-to-official-server&quot;&gt;Upload to Official Server&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#upload-to-custom-server&quot; id=&quot;markdown-toc-upload-to-custom-server&quot;&gt;Upload to Custom Server&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#install-rocks&quot; id=&quot;markdown-toc-install-rocks&quot;&gt;Install Rocks&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;luarocks-luarocks&quot;&gt;LuaRocks luarocks&lt;/h1&gt;

&lt;p&gt;&quot;LuaRocks&quot; refers to the project name, while &quot;luarocks&quot; and &quot;luarocks-admin&quot; refer to CLI tool.&lt;/p&gt;

&lt;h1 id=&quot;manual-installation&quot;&gt;Manual Installation&lt;/h1&gt;

&lt;h2 id=&quot;build-lua&quot;&gt;Build lua&lt;/h2&gt;

&lt;p&gt;This sections show how to manually compile &lt;a href=&quot;lua.md#luajit&quot;&gt;Lua 5.1&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# fetch source&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; https://www.lua.org/ftp/lua-5.1.4.tar.gz
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xf&lt;/span&gt; lua-5.1.4.tar.gz

&lt;span class=&quot;c&quot;&gt;# customization options&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make pecho
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make lecho

&lt;span class=&quot;c&quot;&gt;# determine the platform compatiblity&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make

&lt;span class=&quot;c&quot;&gt;# make&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make linux
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# install&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/usr/local/bin/lua &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;build-luarocks&quot;&gt;Build luarocks&lt;/h2&gt;

&lt;p&gt;In this section, we will demonstrate how to &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/&quot;&gt;install Luarocks&lt;/a&gt; from source.&lt;/p&gt;

&lt;p&gt;Firstly, we install the dependency lib &lt;em&gt;lua-devel&lt;/em&gt; as below. We can avoid this if we have &lt;a href=&quot;#build-lua&quot;&gt;manually built Lua&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 tmp]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;lua-devel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now compile Luarocks:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /tmp

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 tmp]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget https://luarocks.org/releases/luarocks-3.9.0.tar.gz
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 tmp]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xzpvf&lt;/span&gt; luarocks-3.9.0.tar.gz
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 tmp]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;luarocks-3.9.0/
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 luarocks-3.9.0]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./configure &lt;span class=&quot;nt&quot;&gt;--with-lua-include&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/include
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 luarocks-3.9.0]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 luarocks-3.9.0]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 luarocks-3.9.0]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks search lua-cassandra

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 luarocks-3.9.0]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@ip-172-31-16-59 ~]# &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# .bash_profile&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/bin:/usr/local/bin

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@ip-172-31-16-59 ~]# &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-16-59 luarocks-3.9.0]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; luarocks &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For more details regarding configuring Luarocks, please check the section &lt;a href=&quot;#config&quot;&gt;config&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;rocks&quot;&gt;rocks&lt;/h1&gt;

&lt;p&gt;The term &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/Types-of-rocks&quot;&gt;rock&lt;/a&gt; refers to a ZIP archive in the &quot;.rock&quot; extention, containing two kinds of source files as follows.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/Rockspec-format&quot;&gt;.rockspec&lt;/a&gt;. We can generate a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rockspec&lt;/code&gt; template quickly according to &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/write_rockspec&quot;&gt;write_rockspec&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Source code, mainly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.lua&lt;/code&gt; and may include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.c&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are 3 types of rocks as shown below. They differ mainly in the format of the source code part. Please read the &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/Types-of-rocks&quot;&gt;official doc&lt;/a&gt; for more details.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Source Rock (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.src.rock&lt;/code&gt;). The source code is ZIPped as it is. It is usually &lt;a href=&quot;upload-rocks&quot;&gt;uploaded&lt;/a&gt; to &lt;a href=&quot;#rocks-servers&quot;&gt;rocks servers&lt;/a&gt; by &lt;a href=&quot;#upload-to-official-server&quot;&gt;luarocks upload&lt;/a&gt; or &lt;a href=&quot;#upload-to-custom-server&quot;&gt;luarocks-admin&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;The next two types are for &lt;em&gt;installation&lt;/em&gt; purpose.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Binary Rock (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&amp;lt;system-arch&amp;gt;.rock&lt;/code&gt;). This installation type include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.c&lt;/code&gt; source code but compiled to the platform-specific C module.&lt;/p&gt;

    &lt;p&gt;Can be installed directly to the specific platform.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Pure-Lua Rock (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.all.rock&lt;/code&gt;). This installation type contains only Lua code. The ZIP organizes the source rock according to the &lt;a href=&quot;#rocks-servers&quot;&gt;rock tree structure&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;It can be installed directly independent of platforms, but does not guarantee running everywhere. The Lua code might depend on &lt;a href=&quot;lua.md#luajit&quot;&gt;external FFI C modules&lt;/a&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;os.execute(&amp;lt;cmd&amp;gt;)&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Please refer to the section &lt;a href=&quot;#create-rocks&quot;&gt;Create Rocks&lt;/a&gt; on how to create rocks.&lt;/p&gt;

&lt;h1 id=&quot;rocks-servers&quot;&gt;rocks servers&lt;/h1&gt;

&lt;p&gt;We have two kinds of &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/Rocks-repositories&quot;&gt;Rock Repository&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;#config&quot;&gt;rocks servers&lt;/a&gt;, can be an URL (e.g. Github repo) or a local pathname (local server). For examle, the official (default) rocks server URL is &lt;a href=&quot;https://luarocks.org&quot;&gt;https://luarocks.org&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;We can &lt;a href=&quot;#upload-rocks&quot;&gt;upload&lt;/a&gt; rocks to and &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/download-%28command%29&quot;&gt;download&lt;/a&gt; rocks from rocks servers&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;root@0d3fe341fc88:/# luarocks &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;luacov &lt;span class=&quot;nt&quot;&gt;--server&lt;/span&gt; https://kong.github.io/kongrocks-dev/rocks/
Installing https://kong.github.io/kongrocks-dev/rocks/luacov-0.16.0-1.src.rock

luacov 0.16.0-1 depends on lua &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; 5.1 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;5.1-1 provided by VM: success&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
luacov 0.16.0-1 depends on datafile &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0.10-1 installed: success&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
luacov 0.16.0-1 is now installed &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; /usr/local &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;license: MIT&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/Rocks-repositories#rocktree-structure&quot;&gt;rocks trees&lt;/a&gt;, is a local pathname, to where we &lt;a href=&quot;#install-rocks&quot;&gt;install rocks&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A rock repository contains three types of files.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#rocks&quot;&gt;rock&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#rocks&quot;&gt;.rockspec&lt;/a&gt;: optional as it is already in the rock.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#upload-to-custom-server&quot;&gt;manifest&lt;/a&gt; file.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;config&quot;&gt;config&lt;/h1&gt;

&lt;p&gt;To show current config.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# list all&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks config

&lt;span class=&quot;c&quot;&gt;# list only one entry&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks config rocks_servers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is an example to customize &lt;a href=&quot;#rocks-servers&quot;&gt;rocks_servers&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- ~/.luarocks/config-5.4.lua&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rocks_servers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;https://dummy:&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os_getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;GITHUB_TOKEN&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;@raw.githubusercontent.com/Kong/kongrocks/main/rocks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;-- internal rocks server&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;https://luarocks.org&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;-- official rocks server&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;https://raw.githubusercontent.com/rocks-moonscript-org/moonrocks-mirror/master/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;https://luafr.org/luarocks/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please refer to &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/Config-file-format#user-content-Locations&quot;&gt;official config file&lt;/a&gt; and &lt;a href=&quot;https://www.zhstar.win/2023/01/20/emacs-lsp/&quot;&gt;Emacs LSP example&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;create-rocks&quot;&gt;Create Rocks&lt;/h1&gt;

&lt;p&gt;We &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/Creating-a-rock&quot;&gt;create a rock&lt;/a&gt; using &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/pack&quot;&gt;luarocks pack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Firstly, make sure &lt;em&gt;zip&lt;/em&gt; is available.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;zip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are two methods listed as follows.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Given a &lt;a href=&quot;#rocks&quot;&gt;.rockspec file&lt;/a&gt;, we create a &lt;a href=&quot;#rocks&quot;&gt;Source Rock&lt;/a&gt; based on source code downloaded.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks pack ./lua-resty-session/lua-resty-session-4.0.5-1.rockspec

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;lua-resty-session-4.0.5-1.src.rock
   
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file lua-resty-session-4.0.5-1.src.rock
lua-resty-session-4.0.5-1.src.rock: Zip archive data, at least v2.0 to extract, compression &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;deflate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Given a module installed in a &lt;a href=&quot;#rocks-servers&quot;&gt;rocks tree&lt;/a&gt;, we can create a &lt;a href=&quot;#rocks&quot;&gt;Binary Rock&lt;/a&gt; or a &lt;a href=&quot;#rocks&quot;&gt;Pure-Lua Rock&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;From the example below, we find &lt;em&gt;dkjson&lt;/em&gt; is a Pure-Lua Rock (without C modules).&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks list dkjson
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks show dkjson

&lt;span class=&quot;c&quot;&gt;# version &quot;2.6-1&quot; is optional; default to latest.&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks pack &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--verbose&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; dkjson &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2.6-1]

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;dkjson-2.6-1.all.rock

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file dkjson-2.6-1.all.rock
dkjson-2.6-1.all.rock: Zip archive data, at least v2.0 to extract, compression &lt;span class=&quot;nv&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;deflate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Apart from &lt;em&gt;luarocks pack&lt;/em&gt;, we can also use &lt;a href=&quot;#upload-to-custom-server&quot;&gt;luarocks build --pack-binary-rock&lt;/a&gt; to create a Binary Rock (with C modules) or a Pure-Lua Rock. This is a better way as it does not require the rock to be installed.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;upload-rocks&quot;&gt;Upload Rocks&lt;/h1&gt;

&lt;h2 id=&quot;upload-to-official-server&quot;&gt;Upload to Official Server&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/upload&quot;&gt;Luarocks upload&lt;/a&gt; uploads both the .rockspec and the Source Rock to the &lt;a href=&quot;#rocks-servers&quot;&gt;official rocks_server&lt;/a&gt;. We must provide the &lt;a href=&quot;#rocks&quot;&gt;.rockspec&lt;/a&gt; file. If the Source Rock is not provided, it would be &lt;a href=&quot;#create-rocks&quot;&gt;create&lt;/a&gt; on the fly.&lt;/p&gt;

&lt;p&gt;Offer API key on CLI.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# switch to temporary directory&lt;/span&gt;
16:11:41 zachary@Zacharys-MacBook-Pro ~/workspace/resty-redis-cluster
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/misc/

16:15:30 zachary@Zacharys-MacBook-Pro ~/misc
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks upload &lt;span class=&quot;nt&quot;&gt;--api-key&lt;/span&gt; xxxyyyzzz ~/workspace/resty-redis-cluster/kong-redis-cluster-1.3.0-0.rockspec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, configure API key in the upload config.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;11:11:00 zachary@Zacharys-MacBook-Pro ~
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; ~/.luarocks/upload_config.lua
key &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;xxxyyyzzz&quot;&lt;/span&gt;
server &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://luarocks.org&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# switch to temporary directory&lt;/span&gt;
16:11:41 zachary@Zacharys-MacBook-Pro ~/workspace/resty-redis-cluster
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/misc/

16:15:30 zachary@Zacharys-MacBook-Pro ~/misc
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks upload ~/workspace/resty-redis-cluster/kong-redis-cluster-1.3.0-0.rockspec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can optionally, remove the temporary Source Rock.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;16:15:30 zachary@Zacharys-MacBook-Pro ~/misc
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;kong-redis-cluster-1.3.0-0.src.rock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verify the new rock is available from the official rocks server.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;16:16:29 zachary@Zacharys-MacBook-Pro ~/misc
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks search kong-redis-cluster &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1.3.0]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To upload rocks to &lt;a href=&quot;#config&quot;&gt;custom rocks servers&lt;/a&gt;, please refer to &lt;a href=&quot;#upload-to-custom-server&quot;&gt;luarocks-admin&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;upload-to-custom-server&quot;&gt;Upload to Custom Server&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;#upload-to-official-server&quot;&gt;luarocks upload&lt;/a&gt; uploads only Source Rock to only the &lt;em&gt;official&lt;/em&gt; rocks server. We can upload any type of rocks to any &lt;a href=&quot;#config&quot;&gt;custom rocks servers&lt;/a&gt;, by &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/make-manifest&quot;&gt;luarocks-admin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Manuall method.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Copy the .rockspec to the custom rocks server.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone git@github.com:Kong/kongrocks.git
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; FTI-5247
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/workspace/kongrocks

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; ~/workspace/ce2ee/distribution/kong-openid-connect/kong-openid-connect-2.5.6-1.rockspec ./rocks/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;#create-rocks&quot;&gt;Create Source Rock&lt;/a&gt; and copy it to the custom rocks server.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/misc
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks pack ~/workspace/ce2ee/distribution/kong-openid-connect/kong-openid-connect-2.5.6-1.rockspec
   
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;kong-openid-connect-2.5.6-1.src.rock
   
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; ~/misc/kong-openid-connect-2.5.6-1.src.rock ./rocks/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This is optional but highly recommended.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;#create-rocks&quot;&gt;Create Binary Rock or Pure-Lua Rock&lt;/a&gt; and copy it to the custom rocks server.&lt;/p&gt;

    &lt;p&gt;We pass the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--pack-binary-rock&lt;/code&gt; to &lt;a href=&quot;#install-rocks&quot;&gt;luarocks build&lt;/a&gt; to &lt;a href=&quot;#create-rocks&quot;&gt;skip rock installation&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/misc
   
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks build &lt;span class=&quot;nt&quot;&gt;--pack-binary-rock&lt;/span&gt; ~/workspace/ce2ee/distribution/kong-openid-connect/kong-openid-connect-2.5.6-1.rockspec
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks build &lt;span class=&quot;nt&quot;&gt;--pack-binary-rock&lt;/span&gt; kong-openid-connect-2.5.6-1.src.rock

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;kong-openid-connect-2.5.6-1.all.rock
   
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; ~/misc/kong-openid-connect-2.5.6-1.all.rock ./rocks/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This is optional as &lt;a href=&quot;#rocks&quot;&gt;Binary Rock or Pure-Lua Rock&lt;/a&gt; is mainly for installation to a specific platform. You are recommended to skip this part.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Update &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/Manifest-file-format&quot;&gt;manifest&lt;/a&gt; of the custom rocks server.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks-admin make-manifest ./rocks/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;A rocks server has only one manifest file to record all available .rockspec and rocks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Sync the change from local repository to remote repository.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git add &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; origin &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The manual method described above is fairly flexibile. However, we can make use of &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/add&quot;&gt;luarocks-admin add&lt;/a&gt; and &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/remove-%28luarocks-admin%29&quot;&gt;luarocks-admin remove&lt;/a&gt; as they automatically update the manifest file. The limitation is they handle only one rock at a time. See example below.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/misc

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks pack kong-openid-connect-2.5.6-2.rockspec
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks build &lt;span class=&quot;nt&quot;&gt;--pack-binary-rock&lt;/span&gt; kong-openid-connect-2.5.6-2.src.rock
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls
&lt;/span&gt;kong-openid-connect-2.5.6-2.all.rock    kong-openid-connect-2.5.6-2.rockspec    kong-openid-connect-2.5.6-2.src.rock

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/workspace/kongrocks
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks-admin add &lt;span class=&quot;nt&quot;&gt;--server&lt;/span&gt; ~/workspace/kongrocks/rocks/ ~/misc/kong-openid-connect-2.5.6-2.rockspec
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks-admin add &lt;span class=&quot;nt&quot;&gt;--server&lt;/span&gt; ~/workspace/kongrocks/rocks/ ~/misc/kong-openid-connect-2.5.6-2.src.rock
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks-admin add &lt;span class=&quot;nt&quot;&gt;--server&lt;/span&gt; ~/workspace/kongrocks/rocks/ ~/misc/kong-openid-connect-2.5.6-2.all.rock

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pay attention that, we explicitly set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--server&lt;/code&gt; to overwrite the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rocks_servers&lt;/code&gt; in &lt;a href=&quot;#config&quot;&gt;config file&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;install-rocks&quot;&gt;Install Rocks&lt;/h1&gt;

&lt;p&gt;We install a &lt;a href=&quot;#rocks&quot;&gt;Binary Rock or Pure-Lua Rock&lt;/a&gt; to the &lt;a href=&quot;#rocks-servers&quot;&gt;rocks tree&lt;/a&gt; on local host.&lt;/p&gt;

&lt;p&gt;We can either manually add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.lua&lt;/code&gt; file to &lt;a href=&quot;lua.md#lua_path&quot;&gt;LUA_PATH&lt;/a&gt;, or invoke the following commands.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/build&quot;&gt;luarocks build&lt;/a&gt; compiles Binary Rock or Pure-Lua Rock based on Source Rock &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/download-%28command%29&quot;&gt;downloaded&lt;/a&gt; from rocks servers, and then install it.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/make&quot;&gt;luarocks make&lt;/a&gt; differs from &lt;em&gt;luarocks build&lt;/em&gt; in that it compiles Binary Rock or Pure-Lua Rock from the source code in local dev environment. This is very useful when when we want to debug the code.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/install&quot;&gt;luarocks install&lt;/a&gt; installs a local Binary Rock or Pure-Lua Rock file, or falls back to &lt;em&gt;luarocks build&lt;/em&gt; when given a .rockspec file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;See &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/luarocks#overview-of-the-difference-between-make-build-install-and-pack&quot;&gt;https://github.com/luarocks/luarocks/wiki/luarocks#overview-of-the-difference-between-make-build-install-and-pack&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Golden Image</title>
   <link href="/2024/02/19/golden-image/"/>
   <updated>2024-02-19T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2024/02/19/golden-image</id>
   <content type="html">&lt;p&gt;&lt;em&gt;golden image&lt;/em&gt; or &lt;em&gt;master&lt;/em&gt; image, in the software industry, refers to a &lt;em&gt;base&lt;/em&gt; Docker image built from scratch. Once build, no further changes are allowed.&lt;/p&gt;

&lt;p&gt;Based on the golden image, we generate &lt;em&gt;distributable&lt;/em&gt; images that are ready to be deployed in production environment. Distributable images may include programming language runtime, development tools, system administration tools, etc.&lt;/p&gt;

&lt;p&gt;Customers may further customize golden images or distributable images in accord with their platforms.&lt;/p&gt;

&lt;p&gt;The statements above apply to Linux packages (e.g. RPM) as well.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Emacs LSP</title>
   <link href="/2023/01/20/emacs-lsp/"/>
   <updated>2023-01-20T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2023/01/20/emacs-lsp</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#lsp&quot; id=&quot;markdown-toc-lsp&quot;&gt;LSP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#emacs-eglot&quot; id=&quot;markdown-toc-emacs-eglot&quot;&gt;Emacs eglot&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#lsp-servers&quot; id=&quot;markdown-toc-lsp-servers&quot;&gt;LSP Servers&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#cc-clangd&quot; id=&quot;markdown-toc-cc-clangd&quot;&gt;C/C++ clangd&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#lua-lsp&quot; id=&quot;markdown-toc-lua-lsp&quot;&gt;lua-lsp&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#lua-language-server&quot; id=&quot;markdown-toc-lua-language-server&quot;&gt;lua-language-server&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;lsp&quot;&gt;LSP&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot;&gt;Language Server Protocol (LSP)&lt;/a&gt; is originally from Mircosoft and now develops to a standard protocol.&lt;/p&gt;

&lt;p&gt;LSP works in a client/server mode. In this post, the client is usually package of IDE (e.g. Emacs), while the server is specific to programing language (e.g. C/C++).&lt;/p&gt;

&lt;p&gt;To configure Emacs with LSP support, we firstly, install the &lt;em&gt;eglot&lt;/em&gt; in Emacs, then install a language-specific LSP server on your host, and might do some setup in &lt;em&gt;init.el&lt;/em&gt; depending on the LSP server requirement.&lt;/p&gt;

&lt;h1 id=&quot;emacs-eglot&quot;&gt;Emacs eglot&lt;/h1&gt;

&lt;p&gt;Emacs supports LSP by its built-in package &lt;a href=&quot;https://github.com/joaotavora/eglot&quot;&gt;eglot&lt;/a&gt; or 3rd-party package &lt;a href=&quot;https://github.com/emacs-lsp/lsp-mode&quot;&gt;lsp-mode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;eglot&lt;/em&gt; has less features but requires less dependencies. What is more, it is official!&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;To install the &lt;em&gt;eglot&lt;/em&gt; client, just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x package-install RET eglot RET&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;To start &lt;em&gt;eglot&lt;/em&gt; for a LSP.
    &lt;ol&gt;
      &lt;li&gt;Manually run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x eglot&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Automatically by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(add-hook &apos;foo-mode-hook &apos;eglot-ensure)&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;To turn off &lt;em&gt;eglot&lt;/em&gt; and LSP.
    &lt;ol&gt;
      &lt;li&gt;Manually run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x eglot-shutdown&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Automatically by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(setq eglot-autoshutdown t)&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;lsp-servers&quot;&gt;LSP Servers&lt;/h1&gt;

&lt;h2 id=&quot;cc-clangd&quot;&gt;C/C++ clangd&lt;/h2&gt;

&lt;p&gt;Install the C/C++ LSP server &lt;a href=&quot;https://clangd.llvm.org/installation&quot;&gt;clangd&lt;/a&gt; on Arch Linux.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; clang

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;clangd &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure the value of variable &lt;em&gt;eglot-server-programs&lt;/em&gt; contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c-mode&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c++-mode&lt;/code&gt;. All the languages major mode listed &lt;a href=&quot;https://github.com/joaotavora/eglot#connecting-to-a-server&quot;&gt;here&lt;/a&gt; in is enabed by default.&lt;/p&gt;

&lt;p&gt;Please open up a C/C++ source file and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x eglot&lt;/code&gt;. You will find LSP server &lt;em&gt;clangd&lt;/em&gt; is automatically launched on your host, as the child process of Emacs. To shutdown the LSP server, just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x eglot-shutdown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, we&apos;d like to automatically launch the LSP server upon a C/C++ source file is loaded. Add the following contents &lt;em&gt;init.el&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;eglot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;c-mode-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;eglot-ensure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;c++-mode-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;eglot-ensure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;lua-lsp&quot;&gt;lua-lsp&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;deprecated; see &lt;a href=&quot;#lua-language-server&quot;&gt;lua-language-server&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This section assumes we are in Arch Linux system with mutliple Lua versions installed (e.g. &lt;em&gt;extra/lua53&lt;/em&gt; and &lt;em&gt;extra/lua54&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;To install &lt;a href=&quot;https://github.com/Alloyed/lua-lsp&quot;&gt;lua-lsp&lt;/a&gt;, we should install Lua package manager &lt;em&gt;luarocks&lt;/em&gt; first.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; luarocks
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Default Luarocks &lt;a href=&quot;https://github.com/luarocks/luarocks/wiki/Config-file-format&quot;&gt;config&lt;/a&gt; (just a Lua script) is located under &lt;em&gt;/etc/luarocks&lt;/em&gt;. We can inspect the &lt;em&gt;full&lt;/em&gt; configuration of Lua &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5.3&lt;/code&gt; as below.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks &lt;span class=&quot;nt&quot;&gt;--lua-version&lt;/span&gt; 5.3 config &lt;span class=&quot;nt&quot;&gt;--scope&lt;/span&gt; user
config_files &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
   nearest &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/etc/luarocks/config-5.3.lua&quot;&lt;/span&gt;,
   system &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      file &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/etc/luarocks/config-5.3.lua&quot;&lt;/span&gt;,
      found &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
   user &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      file &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/home/outsinre/.luarocks/config-5.3.lua&quot;&lt;/span&gt;,
      found &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; skipped
&lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt;
rocks_trees &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      name &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;,
      root &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/home/outsinre/.luarocks&quot;&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
   &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      name &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;system&quot;&lt;/span&gt;,
      root &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/usr&quot;&lt;/span&gt;
   &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rocks_trees&lt;/code&gt; refers the the root dir storing rocks contents. To avoid conflicts, we&apos;d better configure different rocks tree for different Lua versions. Take Lua &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5.3&lt;/code&gt; for example, we will configure its rocks tree to &lt;em&gt;~/.luarocks53&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let&apos;s change the current user&apos;s rocks tree for Lua &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5.3&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.config/luarocks/
~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /etc/luarocks/config-5.3.lua .config/luarocks/

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vim .config/luarocks/config-5.3.lua
&lt;span class=&quot;o&quot;&gt;&amp;gt;{&lt;/span&gt; name &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;user&quot;&lt;/span&gt;, root &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; home .. &lt;span class=&quot;s2&quot;&gt;&quot;/.luarocks53&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks &lt;span class=&quot;nt&quot;&gt;--lua-version&lt;/span&gt; 5.3 config &lt;span class=&quot;nt&quot;&gt;--scope&lt;/span&gt; user
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, we install &lt;em&gt;lua-lsp&lt;/em&gt; by explicitly provide the rocks tree.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# please omit option &apos;--local&apos;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;luarocks &lt;span class=&quot;nt&quot;&gt;--lua-version&lt;/span&gt; 5.3 &lt;span class=&quot;nt&quot;&gt;--tree&lt;/span&gt; ~/.luarocks53 &lt;span class=&quot;nt&quot;&gt;--server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;http://luarocks.org/dev &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;lua-lsp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, we add the &lt;em&gt;lua-lsp&lt;/em&gt; binary to PATH.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ~/.bash_profile&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;luarocks &lt;span class=&quot;nt&quot;&gt;--lua-version&lt;/span&gt; 5.3 path&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The built-in method above is provided by Luarocks but it exports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUA_PATH&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUA_CPATH&lt;/code&gt; as well. We may just want to set &quot;PATH&quot;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nano &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; ~/.bash_profile
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.luarocks53/bin:&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To automatically launch &lt;em&gt;lua-lsp&lt;/em&gt;, add the following lines to &lt;em&gt;init.el&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;eglot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;lua-mode-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;eglot-ensure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Repeat above steps for other Lua versions.&lt;/p&gt;

&lt;h2 id=&quot;lua-language-server&quot;&gt;lua-language-server&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;#lua-lua-lsp&quot;&gt;lua-lsp&lt;/a&gt; has not been updated for years, and so we swtich the &lt;a href=&quot;https://github.com/LuaLS/lua-language-server/&quot;&gt;lua-language-server&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let&apos;s install &quot;lua-language-server&quot; &lt;a href=&quot;https://github.com/LuaLS/lua-language-server/wiki/Getting-Started#command-line&quot;&gt;manually&lt;/a&gt; per-user.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget https://github.com/LuaLS/lua-language-server/releases/download/3.6.19/lua-language-server-3.6.19-linux-x64.tar.gz

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/.local/share/lua-language-server

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xzvf&lt;/span&gt; lua-language-server-3.6.19-linux-x64.tar.gz &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; ~/.local/share/lua-language-server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We cannot add &lt;em&gt;lua-language-server&lt;/em&gt; to &quot;PATH&quot; directly, instead we must &lt;a href=&quot;https://github.com/LuaLS/lua-language-server/wiki/Getting-Started#command-line&quot;&gt;create a wrapper&lt;/a&gt;, namely &lt;em&gt;~/bin/lsp-lua&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.local/share/lua-language-server/bin/lua-language-server&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--configpath=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.local/share/lua-language-server/settings.lua&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now let&apos;s have a try.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;lsp-lua &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
3.6.19
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;lua-language-server&lt;/em&gt; by default is &lt;a href=&quot;https://github.com/joaotavora/eglot#connecting-to-a-server&quot;&gt;not&lt;/a&gt; added to &lt;a href=&quot;#emacs-eglot&quot;&gt;eglot&lt;/a&gt;. So, we should &lt;a href=&quot;https://joaotavora.github.io/eglot/#Eglot-and-LSP-Servers&quot;&gt;manually set it up&lt;/a&gt; in &lt;em&gt;init.el&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;eglot-server-programs
             &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lua&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;~/bin/lsp-lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hook&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;lua-mode-hook &apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eglot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ensure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Restart Emacs and open a Lua file, &lt;em&gt;eglot&lt;/em&gt; would automatically invokes &lt;em&gt;~/bi/lsp-lua&lt;/em&gt; to launch &lt;em&gt;lua-language-server&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Before closing this section, let&apos;s &lt;a href=&quot;https://github.com/LuaLS/lua-language-server/wiki/Configuration-File&quot;&gt;configure&lt;/a&gt; &lt;em&gt;lua-language-server&lt;/em&gt; a bit. Remember that, &lt;em&gt;~/bin/lsp-lua&lt;/em&gt; has specified the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--configpath&lt;/code&gt; to configurations from a Lua file &lt;em&gt;settings.lua&lt;/em&gt; as follows. Plese read &lt;a href=&quot;https://github.com/LuaLS/lua-language-server/wiki/Settings&quot;&gt;Settings&lt;/a&gt; for a complete list of parameters.&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Lua&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;runtime.version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Lua 5.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;completion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;callSnippet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Both&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;displayContext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;keywordSnippet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Both&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;hint.enable&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;format.enable&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To format current buffer, just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x: eglot-format-buffer&lt;/code&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>OpenResty</title>
   <link href="/2023/01/02/openresty/"/>
   <updated>2023-01-02T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2023/01/02/openresty</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#grab-sources&quot; id=&quot;markdown-toc-grab-sources&quot;&gt;Grab Sources&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#verify-sources&quot; id=&quot;markdown-toc-verify-sources&quot;&gt;Verify Sources&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#build-binary&quot; id=&quot;markdown-toc-build-binary&quot;&gt;Build Binary&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#quickstart&quot; id=&quot;markdown-toc-quickstart&quot;&gt;Quickstart&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#macos&quot; id=&quot;markdown-toc-macos&quot;&gt;macOS&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This post presents the way to manually build &lt;a href=&quot;http://openresty.org&quot;&gt;OpenResty&lt;/a&gt; on archlinux. For a quick playaround, try with &lt;a href=&quot;https://hub.docker.com/r/openresty/openresty&quot;&gt;Docker image&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;grab-sources&quot;&gt;Grab Sources&lt;/h1&gt;

&lt;p&gt;Download sources.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# source&lt;/span&gt;
14:47:22 outsinre@zhtux ~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; https://openresty.org/download/openresty-1.21.4.1.tar.gz

&lt;span class=&quot;c&quot;&gt;# signature&lt;/span&gt;
14:47:33 outsinre@zhtux ~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; https://openresty.org/download/openresty-1.21.4.1.tar.gz.asc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;verify-sources&quot;&gt;Verify Sources&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://www.zhstar.win/2016/02/13/gnupg/#importing-keys&quot;&gt;Import and sign&lt;/a&gt; the public PGP key of Yichun Zhang A0E98066&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;14:47:33 outsinre@zhtux ~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--recv-key&lt;/span&gt; A0E98066

&lt;span class=&quot;c&quot;&gt;# locally sign the public key&lt;/span&gt;
15:02:08 outsinre@zhtux ~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--edit-key&lt;/span&gt; A0E98066
gpg &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;GnuPG&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2.2.40&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; Copyright &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


pub  rsa2048/B550E09EA0E98066
     created: 2013-02-18  expires: never       usage: SC
     trust: unknown       validity: unknown
sub  rsa2048/9C86AC14130DD88B
     created: 2013-02-18  expires: never       usage: E
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; unknown] &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; Yichun Zhang &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;agentzh&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &amp;lt;agentzh@gmail.com&amp;gt;

gpg&amp;gt; lsign 1

pub  rsa2048/B550E09EA0E98066
     created: 2013-02-18  expires: never       usage: SC
     trust: unknown       validity: unknown
 Primary key fingerprint: 2545 1EB0 8846 0026 195B  D62C B550 E09E A0E9 8066

     Yichun Zhang &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;agentzh&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &amp;lt;agentzh@gmail.com&amp;gt;

Are you sure that you want to sign this key with your
key &lt;span class=&quot;s2&quot;&gt;&quot;Zhu Cac (gnupg-rsa-4096) &amp;lt;zhucac@outlook.com&amp;gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;38DA5BA4AABFC8FA&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

The signature will be marked as non-exportable.

Really sign? &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;y/N&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; y

gpg&amp;gt; save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verfiy sources.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;15:07:44 outsinre@zhtux ~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--verify&lt;/span&gt; openresty-1.21.4.1.tar.gz.asc openresty-1.21.4.1.tar.gz
gpg: Signature made Tue 17 May 2022 03:29:41 AM CST
gpg:                using RSA key B550E09EA0E98066
gpg: Good signature from &lt;span class=&quot;s2&quot;&gt;&quot;Yichun Zhang (agentzh) &amp;lt;agentzh@gmail.com&amp;gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;full]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;build-binary&quot;&gt;Build Binary&lt;/h1&gt;

&lt;p&gt;Extract sources.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;15:17:29 outsinre@zhtux ~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xzpvf&lt;/span&gt; openresty-1.21.4.1.tar.gz
15:17:41 outsinre@zhtux ~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;openresty-1.21.4.1

15:19:31 outsinre@zhtux ~/misc/openresty-1.21.4.1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-la&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;auto
total 116
drwxrwxr-x  5 outsinre outsinre  4096 May 16  2022 &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
drwxr-xr-x  6 outsinre outsinre  4096 Jan  2 15:17 ..
&lt;span class=&quot;nt&quot;&gt;-rw-rw-r--&lt;/span&gt;  1 outsinre outsinre 22924 May 16  2022 COPYRIGHT
&lt;span class=&quot;nt&quot;&gt;-rw-rw-r--&lt;/span&gt;  1 outsinre outsinre  8974 May 16  2022 README-windows.txt
&lt;span class=&quot;nt&quot;&gt;-rw-rw-r--&lt;/span&gt;  1 outsinre outsinre  4689 May 16  2022 README.markdown
drwxrwxr-x 46 outsinre outsinre  4096 May 16  2022 bundle
&lt;span class=&quot;nt&quot;&gt;-rwxrwxr-x&lt;/span&gt;  1 outsinre outsinre 51290 May 16  2022 configure
drwxrwxr-x  2 outsinre outsinre  4096 May 16  2022 patches
drwxrwxr-x  2 outsinre outsinre  4096 May 16  2022 util
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Configure the build. We enable the &lt;a href=&quot;http://nginx.org/en/docs/debugging_log.html&quot;&gt;debugging log&lt;/a&gt; and dry run. &lt;a href=&quot;http://openresty.org/en/installation.html#prerequisites&quot;&gt;Make sure&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;perl 5.6.1+&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libpcre&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libssl&lt;/code&gt; is available on the system.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;15:21:21 outsinre@zhtux ~/misc/openresty-1.21.4.1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./configure &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
15:54:41 outsinre@zhtux ~/misc/openresty-1.21.4.1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./configure &lt;span class=&quot;nt&quot;&gt;--with-debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-pcre-jit&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--dry-run&lt;/span&gt;

15:54:41 outsinre@zhtux ~/misc/openresty-1.21.4.1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./configure &lt;span class=&quot;nt&quot;&gt;--with-debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-pcre-jit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Build from sources.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;16:16:43 outsinre@zhtux ~/misc/openresty-1.21.4.1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make
16:16:43 outsinre@zhtux ~/misc/openresty-1.21.4.1&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Set Env. Program &lt;em&gt;openresty&lt;/em&gt; is a symbolic link to program &lt;em&gt;nginx&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# .bash_profile&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;OPENRESTY_PREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/openresty
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OPENRESTY_PREFIX&lt;/span&gt;/bin:&lt;span class=&quot;nv&quot;&gt;$OPENRESTY_PREFIX&lt;/span&gt;/nginx/sbin:&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;quickstart&quot;&gt;Quickstart&lt;/h1&gt;

&lt;p&gt;Check availability.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;16:31:37 outsinre@zhtux ~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;openresty &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt;
nginx version: openresty/1.21.4.1
built by gcc 12.2.0 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;GCC&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
built with OpenSSL 3.0.7 1 Nov 2022
TLS SNI support enabled
configure arguments: &lt;span class=&quot;nt&quot;&gt;--prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/openresty/nginx &lt;span class=&quot;nt&quot;&gt;--with-debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-cc-opt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;-DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC -O2&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../ngx_devel_kit-0.3.1 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../echo-nginx-module-0.62 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../xss-nginx-module-0.06 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../ngx_coolkit-0.2 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../set-misc-nginx-module-0.33 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../form-input-nginx-module-0.12 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../encrypted-session-nginx-module-0.09 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../srcache-nginx-module-0.32 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../ngx_lua-0.10.21 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../ngx_lua_upstream-0.07 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../headers-more-nginx-module-0.33 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../array-var-nginx-module-0.05 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../memc-nginx-module-0.19 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../redis2-nginx-module-0.15 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../redis-nginx-module-0.3.9 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../rds-json-nginx-module-0.15 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../rds-csv-nginx-module-0.09 &lt;span class=&quot;nt&quot;&gt;--add-module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;../ngx_stream_lua-0.0.11 &lt;span class=&quot;nt&quot;&gt;--with-ld-opt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Wl&lt;/span&gt;,-rpath,/usr/local/openresty/luajit/lib &lt;span class=&quot;nt&quot;&gt;--with-pcre-jit&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-stream&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-stream_ssl_module&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-stream_ssl_preread_module&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-http_ssl_module&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;OpenResty ships with program &lt;em&gt;resty&lt;/em&gt; (written with Perl) that can execute OpenResty Lua script.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;16:32:16 outsinre@zhtux ~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;resty &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;local var = 1; print(var)&apos;&lt;/span&gt;
1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To quickly open a simple HTTP server, follow &lt;a href=&quot;http://openresty.org/en/getting-started.html&quot;&gt;OpenResty Getting Started&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;macos&quot;&gt;macOS&lt;/h1&gt;

&lt;p&gt;Check &lt;a href=&quot;https://github.com/openresty/homebrew-brew&quot;&gt;OpenResty brew tap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Install.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap openresty/brew
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;openresty-debug

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;openresty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Export Env.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ~/.bash_profile&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;OPENRESTY_PREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;brew &lt;span class=&quot;nt&quot;&gt;--prefix&lt;/span&gt; openresty/brew/openresty-debug&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OPENRESTY_PREFIX&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/nginx/sbin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$OPENRESTY_PREFIX&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/luajit/bin/:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>GHA</title>
   <link href="/2023/01/01/gha/"/>
   <updated>2023-01-01T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2023/01/01/gha</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#workflow&quot; id=&quot;markdown-toc-workflow&quot;&gt;Workflow&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#runner&quot; id=&quot;markdown-toc-runner&quot;&gt;Runner&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#variables&quot; id=&quot;markdown-toc-variables&quot;&gt;Variables&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#persist-output&quot; id=&quot;markdown-toc-persist-output&quot;&gt;Persist Output&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tokens-and-secrets&quot; id=&quot;markdown-toc-tokens-and-secrets&quot;&gt;Tokens and Secrets&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#security&quot; id=&quot;markdown-toc-security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;workflow&quot;&gt;Workflow&lt;/h1&gt;

&lt;p&gt;Workflows are YMAL files located under the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.github/workflows&lt;/code&gt; directory of your GitHub repo.&lt;/p&gt;

&lt;p&gt;A workflow has one or more &lt;a href=&quot;https://docs.github.com/en/actions/using-jobs&quot;&gt;jobs&lt;/a&gt;. Each job has one or more &lt;em&gt;steps&lt;/em&gt; that execute on a &lt;a href=&quot;#runner&quot;&gt;runner&lt;/a&gt;. Each step is a user-defined Shell script or well-known &lt;a href=&quot;https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions#actions&quot;&gt;actions&lt;/a&gt; like &lt;a href=&quot;https://github.com/actions/checkout&quot;&gt;actions/checkout&lt;/a&gt;. Workflows can be triggered by one or more &lt;a href=&quot;https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows&quot;&gt;events&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is an quick illustration of core concepts.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/gha.webp&quot; alt=&quot;assets/gha.webp&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Check workflow examples at &lt;a href=&quot;https://github.com/outsinre/kong/tree/master/.github/workflows&quot;&gt;https://github.com/outsinre/kong/tree/master/.github/workflows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please refer to &lt;a href=&quot;https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions&quot;&gt;Understanding GitHub Actions&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;runner&quot;&gt;Runner&lt;/h1&gt;

&lt;p&gt;Each GitHub-hosted runner is a new virtual machine (VM) hosted by GitHub with the runner application and other tools preinstalled, and is available with Ubuntu Linux, Windows, or macOS operating systems. When you use a GitHub-hosted runner, machine maintenance and upgrades are taken care of for you.&lt;/p&gt;

&lt;p&gt;Each workflow job has its own standalone runner and specifies the &lt;a href=&quot;https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources&quot;&gt;types of runners&lt;/a&gt; by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runs-on&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;See more details about runner at &lt;a href=&quot;https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners&quot;&gt;Using GitHub-hosted runners&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;variables&quot;&gt;Variables&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.github.com/en/actions/learn-github-actions/variables#about-variables&quot;&gt;Variables&lt;/a&gt; can be categorized into 2 types:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Default variables.
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Default environment (Shell) variables.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;      
${{ env.GITHUB_REPOSITORY }}
      
$GITHUB_REPOSITORY
      
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Default context variables.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;      
${{ github.repository }}
      
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Custom variables.
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Custom environment (Shell) variables defined via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env&lt;/code&gt; key.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;env:
  my_var: foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Custom configuration variables defined at the &quot;Settings&quot; of organization, repository, or environment level.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To access variables, we use &lt;a href=&quot;https://docs.github.com/en/actions/learn-github-actions/contexts&quot;&gt;context&lt;/a&gt; in the form as follows. Most commonly used contexts are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
${{ context.property }}

# example
${{ env.GITHUB_REPOSITORY }}

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

&lt;p&gt;Specially, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env&lt;/code&gt; context has the following two forms:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Workflow syntax as mentioned above.&lt;/li&gt;
  &lt;li&gt;Shell syntax, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$GITHUB_REPOSITORY&lt;/code&gt;. This form is usually used within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run&lt;/code&gt; key.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The difference between the two forms is that the workflow syntax is interpolated before the workflow jobs are sent to a runner, while the Shell syntax is interpolated at runtime.&lt;/p&gt;

&lt;h1 id=&quot;persist-output&quot;&gt;Persist Output&lt;/h1&gt;

&lt;p&gt;We can share values among steps of a job, or even among jobs.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;To share values among steps of a job, please use &lt;a href=&quot;https://docs.github.com/en/actions/learn-github-actions/variables#passing-values-between-steps-and-jobs-in-a-workflow&quot;&gt;GITHUB_ENV&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GITHUB_ENV&lt;/code&gt; is an environment variable storing the pathname of a environment file on the runner. We can access it via Shell syntax in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run&lt;/code&gt; steps and workflow syntax in non-Shell context. See &lt;a href=&quot;https://docs.github.com/en/actions/learn-github-actions/variables#using-the-env-context-to-access-environment-variable-values&quot;&gt;Using the env context to access environment variable values&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   
# define in a step
echo &quot;MY_VAR=myValue&quot; &amp;gt;&amp;gt; $GITHUB_ENV

# reference in another step
${MY_VAR}
# -or-
${{ env.MY_VAR }}
   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;However, in the well-know &lt;a href=&quot;https://github.com/Kong/kong/pull/12021/&quot;&gt;actions/github-script&lt;/a&gt;, we access the environment variables via &lt;a href=&quot;https://nodejs.org/dist/latest-v8.x/docs/api/process.html#process_process_env&quot;&gt;process.env.my_var&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To share values among jobs, please try the following methods.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Use environment variable &lt;a href=&quot;https://docs.github.com/en/actions/using-jobs/defining-outputs-for-jobs&quot;&gt;GITHUB_OUTPUT&lt;/a&gt; to declare the output of a job. Similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GITHUB_ENV&lt;/code&gt; above, but it can only be accessed with workflow syntax.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;      
# define output1 in a job
run: echo &quot;my_var=hello&quot; &amp;gt;&amp;gt; &quot;$GITHUB_OUTPUT&quot;
output1: ${{ steps.&amp;lt;step-id&amp;gt;.outputs.my_var }}

# reference output1 in another job
${{needs.&amp;lt;job_id&amp;gt;.outputs.output1}}
      
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;Of course, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GITHUB_OUTPUT&lt;/code&gt; can &lt;a href=&quot;https://github.com/orgs/community/discussions/55294&quot;&gt;also&lt;/a&gt; be used to share values among steps of a job.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;      
# reference output1 in another step within the same job
${{ steps.&amp;lt;step-id&amp;gt;.outputs.output1_var }}
      
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;a href=&quot;https://help.github.com/en/actions/automating-your-workflow-with-github-actions/persisting-workflow-data-using-artifacts&quot;&gt;Storing workflow data as artifacts&lt;/a&gt;.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;tokens-and-secrets&quot;&gt;Tokens and Secrets&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;GitHub tokens, namely Personal Access Tokens, are opaque strings (credentials) defined for your GitHub account at &lt;a href=&quot;https://github.com/settings/tokens&quot;&gt;https://github.com/settings/tokens&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;GitHub secrets are names declared at the &quot;Settings&quot; of organization, repository, or repository environment level. Any values (e.g. JSON string) can be assigned to secrets. But to operate the repo, we assign tokens to secrets.&lt;/p&gt;

    &lt;p&gt;Once set, secrets are available to workflows via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;There is a special secret &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt; which is automatically issued by GitHub when a workflow is triggered, and you don not need to create this explicitly. It is different from the personal access tokens. Refer to &lt;a href=&quot;https://docs.github.com/en/actions/security-guides/automatic-token-authentication&quot;&gt;Automatic token authentication
&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions&quot;&gt;Using secrets in GitHub Actions&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;security&quot;&gt;Security&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Kong/kubernetes-ingress-controller/issues/6907&quot;&gt;Kong does not care about security&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>SELinux</title>
   <link href="/2022/05/15/selinux/"/>
   <updated>2022-05-15T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2022/05/15/selinux</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#utilities&quot; id=&quot;markdown-toc-utilities&quot;&gt;Utilities&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#status&quot; id=&quot;markdown-toc-status&quot;&gt;Status&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#modes&quot; id=&quot;markdown-toc-modes&quot;&gt;Modes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#audit-logs&quot; id=&quot;markdown-toc-audit-logs&quot;&gt;Audit Logs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#boolean-values&quot; id=&quot;markdown-toc-boolean-values&quot;&gt;Boolean Values&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ports&quot; id=&quot;markdown-toc-ports&quot;&gt;Ports&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This post only serves as a quick reference for SELinux. Read &lt;em&gt;whatever&lt;/em&gt; for the design and principle behind.&lt;/p&gt;

&lt;h1 id=&quot;utilities&quot;&gt;Utilities&lt;/h1&gt;

&lt;p&gt;Make sure the following packages are installed.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf provides /usr/sbin/sestatus
policycoreutils
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf list policycoreutils

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf repoquery &lt;span class=&quot;nt&quot;&gt;--provides&lt;/span&gt; /usr/sbin/getenforce
libselinux-utils
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf list libselinux-utils

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf provides /usr/sbin/semanage
policycoreutils-python-utils
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf list policycoreutils-python-utils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;status&quot;&gt;Status&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;getenforce
Enforcing

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Memory protection checking:     actua

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;seinfo
Statistics &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;policy file: /sys/fs/selinux/policy
Policy Version:             31 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;MLS enabled&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Target Policy:              selinux
Handle unknown classes:     allow
  Classes:             132    Permissions:         464
  Sensitivities:         1    Categories:         1024
  Types:              4938    Attributes:          252
  Users:                 8    Roles:                14
  Booleans:            335    Cond. Expr.:         380
  Allow:            110525    Neverallow:            0
  Auditallow:          161    Dontaudit:         10253
  Type_trans:       241591    Type_change:          87
  Type_member:          35    Range_trans:        5781
  Role allow:           37    Role_trans:          420
  Constraints:          72    Validatetrans:         0
  MLS Constrain:        72    MLS Val. Tran:         0
  Permissives:           0    Polcap:                5
  Defaults:              7    Typebounds:            0
  Allowxperm:            0    Neverallowxperm:       0
  Auditallowxperm:       0    Dontauditxperm:        0
  Ibendportcon:          0    Ibpkeycon:             0
  Initial SIDs:         27    Fs_use:               34
  Genfscon:            108    Portcon:             642
  Netifcon:              0    Nodecon:               0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;modes&quot;&gt;Modes&lt;/h1&gt;

&lt;p&gt;SELinux has three modes:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;enforcing: security policy is enforced.&lt;/li&gt;
  &lt;li&gt;permissive: security policy is disabled but log events.&lt;/li&gt;
  &lt;li&gt;disabled: SELinux daemon is not loaded at all.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can changed the modes permanently by &lt;em&gt;/etc/selinux/config&lt;/em&gt; and reboot. Alternaitvely, we can temporarily switch between &lt;em&gt;enforcing&lt;/em&gt; and &lt;em&gt;permissive&lt;/em&gt; on CLI.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# enforcing&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;setenforce 1

&lt;span class=&quot;c&quot;&gt;# permissive&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;setenforce 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;audit-logs&quot;&gt;Audit Logs&lt;/h1&gt;

&lt;p&gt;If SELinux denies an access (e.g. a file), the denial event is logged to &lt;em&gt;/var/log/audit/audit.log&lt;/em&gt;. Sometimes, we call it &quot;Access Vector Cache (AVC) denial&quot;.&lt;/p&gt;

&lt;p&gt;The log may reveal what is the cause of our applications.&lt;/p&gt;

&lt;h1 id=&quot;boolean-values&quot;&gt;Boolean Values&lt;/h1&gt;

&lt;p&gt;SELinux have many built-in boolean values.&lt;/p&gt;

&lt;p&gt;List boolean values by &lt;em&gt;getsebool&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;getsebool &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;h]ttpd_can_network_connect
httpd_can_network_connect &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; off
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can set a boolean value by &lt;em&gt;setsebool&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;setsebool &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; httpd_can_network_connect 1
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;setsebool &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;httpd_can_network_connect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;ports&quot;&gt;Ports&lt;/h1&gt;

&lt;p&gt;Each port number, together with &lt;em&gt;protocol&lt;/em&gt;, belong to a perticular &lt;em&gt;service&lt;/em&gt; (i.e., label). For example, TCP port 22 is for SSH service (TCP).&lt;/p&gt;

&lt;p&gt;List all services.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;semanage port &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
...
ephemeral_port_t               tcp      32768-60999
ephemeral_port_t               udp      32768-60999
...
ssh_port_t                     tcp      22
...
unreserved_port_t              sctp     1024-65535
unreserved_port_t              tcp      61000-65535, 1024-32767
unreserved_port_t              udp      61000-65535, 1024-32767
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are two special services, namely &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ephemeral_port_t&lt;/code&gt; (32768-60999) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unreserved_port_t&lt;/code&gt; (1024-32767,61000-65535).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;seinfo &lt;span class=&quot;nt&quot;&gt;--portcon&lt;/span&gt; 32768

Portcon: 3
   portcon sctp 1024-65535 system_u:object_r:unreserved_port_t:s0
   portcon tcp 32768-60999 system_u:object_r:ephemeral_port_t:s0
   portcon udp 32768-60999 system_u:object_r:ephemeral_port_t:s0

~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;seinfo &lt;span class=&quot;nt&quot;&gt;--portcon&lt;/span&gt; 32767

Portcon: 3
   portcon sctp 1024-65535 system_u:object_r:unreserved_port_t:s0
   portcon tcp 1024-32767 system_u:object_r:unreserved_port_t:s0
   portcon udp 1024-32767 system_u:object_r:unreserved_port_t:s0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://access.redhat.com/solutions/3236651&quot;&gt;By default&lt;/a&gt;, ephemeral ports are &lt;a href=&quot;https://selinux.tycho.nsa.narkive.com/HQcSiIcp/rfc-https-bugzilla-redhat-com-show-bug-cgi-id-1174405&quot;&gt;allowed&lt;/a&gt; but unreserved ports are disallowed. To allow an unreserved port, we just need to add it to a specific other services.&lt;/p&gt;

&lt;p&gt;For example, here is the default allowed HTTP ports:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;semanage port &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;h]ttp_port_t
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To enable/disable a port, we add/delete it from a type and protocol combination.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# add a port&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;semanage port &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; http_port_t &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp 32767

&lt;span class=&quot;c&quot;&gt;# delete a port&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;semanage port &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; http_port_t &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; tcp 32768
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>systemd</title>
   <link href="/2021/07/19/systemd/"/>
   <updated>2021-07-19T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2021/07/19/systemd</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#systemd-manager&quot; id=&quot;markdown-toc-systemd-manager&quot;&gt;systemd manager&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#hierarchy-of-control-groups&quot; id=&quot;markdown-toc-hierarchy-of-control-groups&quot;&gt;Hierarchy of Control Groups&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#systemctl&quot; id=&quot;markdown-toc-systemctl&quot;&gt;systemctl&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#systemd-drop-in&quot; id=&quot;markdown-toc-systemd-drop-in&quot;&gt;systemd drop-in&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#journalctl&quot; id=&quot;markdown-toc-journalctl&quot;&gt;journalctl&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#user-unit&quot; id=&quot;markdown-toc-user-unit&quot;&gt;User Unit&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;systemd-manager&quot;&gt;systemd manager&lt;/h1&gt;

&lt;p&gt;Systemd (system daemon) is a &lt;em&gt;manager&lt;/em&gt; capable of managing both services and the Linux system.&lt;/p&gt;

&lt;p&gt;The daemon locates at &lt;em&gt;/lib/systemd/systemd&lt;/em&gt;, and &lt;em&gt;/sbin/init&lt;/em&gt; is just a symbolic link:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ll /sbin/init
lrwxrwxrwx 1 root root 22 May 18 18:32 /sbin/init -&amp;gt; ../lib/systemd/systemd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At the very boot of the system, systemd runs as the PID 1, namely the system manager instance:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt;
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     0:24 /sbin/init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When a user login, a user manager instance is started for services of that particular account by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user@.service&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;user@.service

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl show user@1000.service

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl status user@1000.service

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eF&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;s]ystemd
jim     572       1  0  4081  9208   7 Jun20 ?        00:00:00 /usr/lib/systemd/systemd &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;hierarchy-of-control-groups&quot;&gt;Hierarchy of Control Groups&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.slice&lt;/code&gt; controls the resources&lt;/li&gt;
  &lt;li&gt;User processes may be started by:
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user@.service&lt;/code&gt; unit.&lt;/li&gt;
      &lt;li&gt;manual startup, like sshd, displayer manager (e.g. initx/gdm), etc.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemd-cgls

Control group /:
-.slice
├─user.slice
│ └─user-1000.slice
│   ├─user@1000.service
│   │ ├─app.slice
│   │ │ ├─dconf.service
│   │ │ │ └─10610 /usr/lib/dconf-service
│   │ │ ├─thunar.service
│   │ │ │ └─47699 /usr/bin/Thunar &lt;span class=&quot;nt&quot;&gt;--daemon&lt;/span&gt;
│   │ │ ├─at-spi-dbus-bus.service
│   │ │ │ ├─ 816 /usr/lib/at-spi-bus-launcher
│   │ │ │ ├─2094 /usr/bin/dbus-daemon &lt;span class=&quot;nt&quot;&gt;--config-file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/share/defaults/at-spi2/accessibility.conf &lt;span class=&quot;nt&quot;&gt;--nofork&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--print-address&lt;/span&gt; 3
│   │ │ │ └─2098 /usr/lib/at-spi2-registryd &lt;span class=&quot;nt&quot;&gt;--use-gnome-session&lt;/span&gt;
│   │ │ └─dbus.service
│   │ │   ├─  648 /usr/bin/dbus-daemon &lt;span class=&quot;nt&quot;&gt;--session&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;systemd: &lt;span class=&quot;nt&quot;&gt;--nofork&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--nopidfile&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--systemd-activation&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--syslog-only&lt;/span&gt;
│   │ │   └─47703 /usr/lib/xfce4/xfconf/xfconfd
│   │ └─init.scope
│   │   ├─572 /usr/lib/systemd/systemd &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt;
│   │   └─573 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;sd-pam&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
│   └─session-1.scope
│     ├─   550 login &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; jim
│     ├─   579 &lt;span class=&quot;nt&quot;&gt;-bash&lt;/span&gt;
│     ├─   589 /usr/bin/ssh-agent &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;
│     ├─   604 /bin/sh /usr/bin/startx
│     ├─   622 xinit /home/jim/.xinitrc &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; /home/jim/.xserverrc :0 vt1 &lt;span class=&quot;nt&quot;&gt;-keeptty&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-auth&lt;/span&gt; /tmp/serverauth.RW8Bv770dV
│     ├─   623 /usr/lib/Xorg &lt;span class=&quot;nt&quot;&gt;-nolisten&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-nolisten&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-keeptty&lt;/span&gt; :0 vt1 &lt;span class=&quot;nt&quot;&gt;-keeptty&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-auth&lt;/span&gt; /tmp/serverauth.RW8Bv770dV vt1
│     ├─   642 awesome
│     ├─   666 xautolock &lt;span class=&quot;nt&quot;&gt;-detectsleep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-time&lt;/span&gt; 3 &lt;span class=&quot;nt&quot;&gt;-locker&lt;/span&gt; slock &lt;span class=&quot;nt&quot;&gt;-corners&lt;/span&gt; 00+0 &lt;span class=&quot;nt&quot;&gt;-cornerdelay&lt;/span&gt; 5 &lt;span class=&quot;nt&quot;&gt;-notify&lt;/span&gt; 5 &lt;span class=&quot;nt&quot;&gt;-notifier&lt;/span&gt; notify-send &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; critical &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; 10000 &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;LOCKING screen in 5 seconds&apos;&lt;/span&gt;
│     ├─   675 fcitx
│     ├─   680 /usr/bin/dbus-daemon &lt;span class=&quot;nt&quot;&gt;--syslog&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--fork&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--print-pid&lt;/span&gt; 4 &lt;span class=&quot;nt&quot;&gt;--print-address&lt;/span&gt; 6 &lt;span class=&quot;nt&quot;&gt;--config-file&lt;/span&gt; /usr/share/fcitx/dbus/daemon.conf
│     ├─   684 /usr/bin/fcitx-dbus-watcher unix:abstract&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tmp/dbus-y7OCHgrxGl,guid&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;98e8dc5f3eed24ce2b4a183c60cf475a 680
│     ├─  2091 emacs &lt;span class=&quot;nt&quot;&gt;--daemon&lt;/span&gt;
│     ├─ 16367 goldendict
│     ├─ 94741 /usr/lib/firefox/firefox
│     ├─ 94901 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-childID&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;-isForBrowser&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 210 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;tab
│     ├─ 94935 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-childID&lt;/span&gt; 3 &lt;span class=&quot;nt&quot;&gt;-isForBrowser&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 5036 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;tab
│     ├─ 95053 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 6216 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;rdd
│     ├─114937 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-childID&lt;/span&gt; 19 &lt;span class=&quot;nt&quot;&gt;-isForBrowser&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 9718 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;tab
│     ├─128993 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-childID&lt;/span&gt; 50 &lt;span class=&quot;nt&quot;&gt;-isForBrowser&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 11032 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;tab
│     ├─155942 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-childID&lt;/span&gt; 64 &lt;span class=&quot;nt&quot;&gt;-isForBrowser&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 11034 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;tab
│     ├─157055 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-childID&lt;/span&gt; 69 &lt;span class=&quot;nt&quot;&gt;-isForBrowser&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 11034 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;tab
│     ├─161533 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-childID&lt;/span&gt; 70 &lt;span class=&quot;nt&quot;&gt;-isForBrowser&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 11035 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;tab
│     ├─165017 st
│     ├─165018 /bin/bash
│     ├─165033 tmux new &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;arch&lt;/span&gt;
│     ├─165035 tmux new &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;arch&lt;/span&gt;
│     ├─165036 &lt;span class=&quot;nt&quot;&gt;-bash&lt;/span&gt;
│     ├─165051 ssh ora1
│     ├─165855 &lt;span class=&quot;nt&quot;&gt;-bash&lt;/span&gt;
│     ├─165867 &lt;span class=&quot;nt&quot;&gt;-bash&lt;/span&gt;
│     ├─165879 ssh ora2
│     ├─166174 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-childID&lt;/span&gt; 95 &lt;span class=&quot;nt&quot;&gt;-isForBrowser&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 11070 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;tab
│     ├─166322 /usr/lib/firefox/firefox &lt;span class=&quot;nt&quot;&gt;-contentproc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-childID&lt;/span&gt; 97 &lt;span class=&quot;nt&quot;&gt;-isForBrowser&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-prefsLen&lt;/span&gt; 11070 &lt;span class=&quot;nt&quot;&gt;-prefMapSize&lt;/span&gt; 239063 &lt;span class=&quot;nt&quot;&gt;-parentBuildID&lt;/span&gt; 20210623174607 &lt;span class=&quot;nt&quot;&gt;-appdir&lt;/span&gt; /usr/lib/firefox/browser 94741 &lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;tab
│     ├─167307 /usr/lib/thunderbird/thunderbird
│     ├─177691 &lt;span class=&quot;nt&quot;&gt;-bash&lt;/span&gt;
│     ├─177791 man systemd
│     ├─177801 less
│     ├─177869 man user@.service
│     ├─177879 less
│     ├─177932 &lt;span class=&quot;nt&quot;&gt;-bash&lt;/span&gt;
│     ├─178007 systemd-cgls
│     └─178008 less
├─init.scope
│ └─1 /sbin/init
└─system.slice
  ├─systemd-udevd.service
  │ └─431 /usr/lib/systemd/systemd-udevd
  ├─polkit.service
  │ └─94871 /usr/lib/polkit-1/polkitd &lt;span class=&quot;nt&quot;&gt;--no-debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;systemctl&quot;&gt;systemctl&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# show installed units on the system&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl list-unit-files &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;pattern]

&lt;span class=&quot;c&quot;&gt;# show all units in memory&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl
&lt;span class=&quot;c&quot;&gt;# filter units in memory&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;service &lt;span class=&quot;nt&quot;&gt;--state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;running &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;list-units &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;pattern]]

&lt;span class=&quot;c&quot;&gt;# reload all installed unit files (e.g. nginx.service)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl daemon-reload
&lt;span class=&quot;c&quot;&gt;# reload daemon config (e.g. nginx.conf)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl reload &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;pattern]

&lt;span class=&quot;c&quot;&gt;# view unit configuration&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mostly default from &apos;systemd&apos; config&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl show &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;pattern]
&lt;span class=&quot;c&quot;&gt;# view unit file&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;pattern]

&lt;span class=&quot;c&quot;&gt;# manage a unit&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;UNIT
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;PATHNAME
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl status/start/stop/restart/disable/mask UNIT
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;name@sub.service

&lt;span class=&quot;c&quot;&gt;# dependency&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; list-dependencies UNIT
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--with-dependencies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; status PATTERN
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;systemd-drop-in&quot;&gt;systemd drop-in&lt;/h2&gt;

&lt;p&gt;It is not unusual when we do not want to modify the shipped unit file but want customization.&lt;/p&gt;

&lt;p&gt;For a particular unit &lt;em&gt;foo.service&lt;/em&gt;, &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/systemd.unit.html&quot;&gt;systemd supports merging&lt;/a&gt; &lt;em&gt;drop-in&lt;/em&gt; files &lt;em&gt;*.conf&lt;/em&gt; stored under the drop-in directory &lt;em&gt;foo.d&lt;/em&gt;. Drop-in directories can be located in &lt;em&gt;/etc/systemd/system&lt;/em&gt;, &lt;em&gt;/usr/lib/systemd/system&lt;/em&gt; or &lt;em&gt;/run/systemd/system&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We can &lt;em&gt;manually&lt;/em&gt; create the drop-in directory and then add or remove drop-in files. If the drop-in directory is empty, then the unit would be cleared!&lt;/p&gt;

&lt;p&gt;Alternatively, &lt;em&gt;systemctl edit&lt;/em&gt; automatically create and/or remove the drop-in directory and drop-in files. After editing, it would call &lt;em&gt;systemctl daemon-reload&lt;/em&gt; automatically.&lt;/p&gt;

&lt;p&gt;The example belows add a few environment variables to the unit file.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl edit kong-enterprise-edition

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;kong-enterprise-edition
...

&lt;span class=&quot;c&quot;&gt;# /etc/systemd/system/kong-enterprise-edition.service.d/override.conf&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Service]
&lt;span class=&quot;nv&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;KONG_NGINX_DAEMON&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;off
&lt;span class=&quot;nv&quot;&gt;Environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;KONG_DATABASE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;off
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If somehow, we want to update the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecStart&lt;/code&gt;, we must firstly prepend an empty directive like the following. Otherwise, there would be two conflicted &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecStart&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://127.0.0.1:2375 --containerd=/run/containerd/containerd.sock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can optionally add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--full&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--force&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--runtime&lt;/code&gt; to &lt;em&gt;systemctl edit&lt;/em&gt;. For details, please refer to man page of &lt;em&gt;systemctl&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If somehow, we want to discard all drop-in directories and drop-in files, then run the command as follows.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl revert kong-enterprise-edition
Removed /etc/systemd/system/kong-enterprise-edition.service.d/override.conf.
Removed /etc/systemd/system/kong-enterprise-edition.service.d.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;journalctl&quot;&gt;journalctl&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# journalctl -xfe&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# journalctl -u nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;user-unit&quot;&gt;User Unit&lt;/h1&gt;

&lt;p&gt;User unit should be under &lt;em&gt;~/.config/systemd/user/&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Firstly, let user unit know the user PATH. At the end of &lt;em&gt;~/.bash_profile&lt;/em&gt;, put the following line.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ~/.bash_profile&lt;/span&gt;
systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; import-environment PATH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check if user unit know the PATH&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; show-environment
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now enable and start user unit.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; daemon-reload

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; status weechat-headless.service
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;weechat-headless.service

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; start weechat-headless.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Public Cloud Infrastructure</title>
   <link href="/2021/07/18/aws/"/>
   <updated>2021-07-18T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2021/07/18/aws</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#general-components&quot; id=&quot;markdown-toc-general-components&quot;&gt;General Components&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#oracle&quot; id=&quot;markdown-toc-oracle&quot;&gt;Oracle&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#glossary&quot; id=&quot;markdown-toc-glossary&quot;&gt;Glossary&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#always-free&quot; id=&quot;markdown-toc-always-free&quot;&gt;Always-free&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#instance-configuration&quot; id=&quot;markdown-toc-instance-configuration&quot;&gt;Instance Configuration&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#linux-configuration&quot; id=&quot;markdown-toc-linux-configuration&quot;&gt;Linux Configuration&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#block-volume&quot; id=&quot;markdown-toc-block-volume&quot;&gt;Block Volume&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#aws&quot; id=&quot;markdown-toc-aws&quot;&gt;AWS&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#amazon-linux-extras&quot; id=&quot;markdown-toc-amazon-linux-extras&quot;&gt;amazon-linux-extras&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#aliyun&quot; id=&quot;markdown-toc-aliyun&quot;&gt;Aliyun&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will presents a general setup on public cloud platform (e.g. AWS) to launch a web server.&lt;/p&gt;

&lt;h1 id=&quot;general-components&quot;&gt;General Components&lt;/h1&gt;

&lt;p&gt;Pay attention to the charging items:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Compute instance, like EC2.
    &lt;ol&gt;
      &lt;li&gt;Running time.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;VPC (Virtual Private Cloud) Network
    &lt;ol&gt;
      &lt;li&gt;Elastic IP.&lt;/li&gt;
      &lt;li&gt;Firewall like Security Group (zone) and Compute iptables.&lt;/li&gt;
      &lt;li&gt;Bandwidth or traffic.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Storage, like EBS (Elastic Block Storage).
    &lt;ol&gt;
      &lt;li&gt;Compute Storage&lt;/li&gt;
      &lt;li&gt;Image storage&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;oracle&quot;&gt;Oracle&lt;/h1&gt;

&lt;p&gt;THINK TWICE before rebooting a instance or detach &lt;em&gt;block volume&lt;/em&gt; from a instance. Check &lt;a href=&quot;#instance-configuration&quot;&gt;Instance Configuration&lt;/a&gt; for details.&lt;/p&gt;

&lt;h2 id=&quot;glossary&quot;&gt;Glossary&lt;/h2&gt;

&lt;p&gt;Oracle Cloud Infrastructure (OCI):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Tenancy. Subscription account, the root account included.&lt;/li&gt;
  &lt;li&gt;User. A login user account, including the Oracle federated OracleIdentityCloudService.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Compartment. A group of resources for different projects, like Finance compartment, Logging compartment etc. Think of compartment as Linux Cgroup or Tess cluster.&lt;/p&gt;

    &lt;p&gt;See &lt;a href=&quot;https://cloud.oracle.com/identity/compartments/explorer?region=ap-seoul-1&quot;&gt;link&lt;/a&gt; for all resources within the root compartment.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Tag namespace. A group of tags applied to resources. Think of tag namespace as Tess namespace - just another dimension of resources organization.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;always-free&quot;&gt;Always-free&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en-us/iaas/Content/FreeTier/freetier_topic-Always_Free_Resources.htm&quot;&gt;Always free resources&lt;/a&gt; does not limit running time or network traffic:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;2 instances.&lt;/li&gt;
  &lt;li&gt;2 public IPs. Can be changed for free.&lt;/li&gt;
  &lt;li&gt;200 GB volume storage (boot volume + block volume) plus 5 volume backups.&lt;/li&gt;
  &lt;li&gt;2 VCN (Virtual Cloud Network).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/en-us/iaas/Content/API/Concepts/cloudshellintro.htm&quot;&gt;Cloud Shell&lt;/a&gt;. Cloud Shell is a browser-based VM and separated from resournces above (e.g. 50 GB standalone storage). We can manage OCI instances through the Cloud Shell.&lt;/p&gt;

    &lt;p&gt;Apart from Cloud Shell, we also have &apos;Web Shell&apos;. Web Shell is a browser-based interface to a particular instance, usually for management.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;instance-configuration&quot;&gt;Instance Configuration&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Create an instance
    &lt;ol&gt;
      &lt;li&gt;Select resources with &quot;Always Free Eligible&quot; label.&lt;/li&gt;
      &lt;li&gt;Select Oracle Linux is recommended. CentOS is deprecated.&lt;/li&gt;
      &lt;li&gt;Instance shape is &quot;VM.Standard.E2.1.Micro&quot;.&lt;/li&gt;
      &lt;li&gt;Upload SSH public key.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Configure VCN. Each VCN includes a VNIC (Virtual Network Interface Card) attached to the instance. The core part of VCN and VNIC is:
    &lt;ol&gt;
      &lt;li&gt;Subnet for internal network.&lt;/li&gt;
      &lt;li&gt;Public IP address. Public IP assigned may be blocked, but we can always got a new one free of charge at: Compute - Instances - Instance Details - Attached VNICs - VNIC Details - IPv4 Addresses.&lt;/li&gt;
      &lt;li&gt;Security List (firewall). Add &quot;ingress rules&quot; to the default &quot;security list&quot;. By default, only port 22 on ingress is allowed. Leave the &quot;Stateless&quot; alone, otherwise you need to add matching &quot;egress rules&quot;. By default, ICMP is blocked; SSH is allowed. Probably, we should enable 80/443.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#block-volume&quot;&gt;Block Volume&lt;/a&gt;. By default, each instance is assigned 50 GB boot volume. However, each account can have up to 200 GB volume.
    &lt;ol&gt;
      &lt;li&gt;Create a 50 GB block volume.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Attach the block volume. When you &quot;terminate&quot; an instance, the block volume attached remain. Be careful over free quota!&lt;/p&gt;

        &lt;p&gt;Step 3 and step 4 below is dangerous! Mount the attached block volume only on demand.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Login and run the iSCSI connect commands. Attention that the block volume use network connection:&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;lsof &lt;span class=&quot;nt&quot;&gt;-nP&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; tcp:3260
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;fdisk &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; /dev/sdb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Either mount the device somewhere (e.g. &quot;/opt&quot;) or &lt;a href=&quot;#block-volume&quot;&gt;extend it to root LVM&lt;/a&gt;.&lt;/p&gt;

        &lt;p&gt;To mount the new device by &quot;/etc/fstab&quot;, remember to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_netdev&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nofail&lt;/code&gt; options, as attached block volumes require network access upon boot.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;CAUTION: before rebooting the instance or detaching the block volume, please &lt;em&gt;revert&lt;/em&gt; step 4 and step 3 above, otherwise we lost contact to our instance, even &lt;a href=&quot;#always-free&quot;&gt;Web/Cloud Shell&lt;/a&gt; would not help!&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/oci-block-volume-reminder.png&quot; alt=&quot;block volume reminder&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Optionally, &lt;a href=&quot;#linux-configuration&quot;&gt;disable OCI plugins&lt;/a&gt;, like the Custom Logs Monitoring. OCI plugins communicate with &lt;a href=&quot;#linux-configuration&quot;&gt;oracle-cloud-agent.service&lt;/a&gt; on instance to collect performance metrics, install OS updates, perform other instance management tasks, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Repeat above steps for another free instance. By default, both instances share the same VCN, subnet and security list.&lt;/p&gt;

&lt;h2 id=&quot;linux-configuration&quot;&gt;Linux Configuration&lt;/h2&gt;

&lt;p&gt;If you are unware of the following actions, just skip it.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Disable or enable Orable Cloud Agent.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl stop oracle-cloud-agent
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl disable oracle-cloud-agent
   
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl stop oracle-cloud-agent-updater
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl disable oracle-cloud-agent-updater
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Disable or enable rpcbind.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl stop rpcbind.service
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl stop rpcbind.socket
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl stop rpcbind.target
   
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl disable rpcbind
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl disable rpcbind.socket
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Optionally disable &lt;em&gt;cockpit.socket&lt;/em&gt; for &lt;a href=&quot;#always-free&quot;&gt;Web Shell&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;You are recommended to leave it open for online instance debug.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;As CentOS is EOL. We should change the mirrorlist.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;s/mirrorlist=/#mirrorlist=/g&apos;&lt;/span&gt; /etc/yum.repos.d/CentOS-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g&apos;&lt;/span&gt; /etc/yum.repos.d/CentOS-&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
   
&lt;span class=&quot;c&quot;&gt;# fix librepo issue&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;python3-librepo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;From now on, &lt;a href=&quot;#instance-configuration&quot;&gt;Oracle Linux is recommended&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Firewall. By default, &lt;a href=&quot;/2017/09/20/firewalld/&quot;&gt;firewalld&lt;/a&gt; is enabled and most ports are disallowed! At least enable 80 and 443.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class=&quot;nt&quot;&gt;--permanent&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--zone&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;public &lt;span class=&quot;nt&quot;&gt;--add-service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;http &lt;span class=&quot;nt&quot;&gt;--add-service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;https
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class=&quot;nt&quot;&gt;--reload&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class=&quot;nt&quot;&gt;--list-all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;To allow a port, we should be both enable it in VCN and on instance.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;block-volume&quot;&gt;Block Volume&lt;/h2&gt;

&lt;p&gt;It is not recommended to extend the block volume into existing LVM as the &lt;a href=&quot;#instance-configuration&quot;&gt;reverting process is complicated&lt;/a&gt;! When rebooting the instance or detaching the block volume, we must revert steps below. See &lt;a href=&quot;#instance-configuration&quot;&gt;Instance Configuration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Firstly, prepare the disk partition:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;fdisk &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;parted &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; opt /dev/sdb

&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mklabel gpt
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; unit s
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; print free
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary xfs 0% 100%
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; name 1 blockvolume
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; print free
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; quit

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;fdisk &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;blkid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, we make a filesystem on the block volume as below. This step is optional as the we will use this partition as LVM, and the filesystem created will be erased!&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mkfs.xfs /deb/sdb1
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;lsblk
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;blkid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let&apos;s inspecting existing LVM. There is only LV created &lt;em&gt;/dev/centosvolume/root&lt;/em&gt; storage of which we will extend soon.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# LVM inspection&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pvscan &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pvdisplay &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
  PV /dev/sda3   VG centosvolume    lvm2 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&amp;lt;39.06 GiB / 0    free]
  Total: 1 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&amp;lt;39.06 GiB] / &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;use: 1 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&amp;lt;39.06 GiB] / &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;no VG: 0 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0   &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vgscan &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vgdisplay &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
  Found volume group &lt;span class=&quot;s2&quot;&gt;&quot;centosvolume&quot;&lt;/span&gt; using metadata &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;lvm2
  
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;lvscan &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;lvdisplay &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
  ACTIVE            &lt;span class=&quot;s1&quot;&gt;&apos;/dev/centosvolume/root&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&amp;lt;39.06 GiB] inherit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Creating PV:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pvcreate /dev/sdb1
WARNING: xfs signature detected on /dev/sdb1 at offset 0. Wipe it? &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;y/n]: y
  Wiping xfs signature on /dev/sdb1.
  Physical volume &lt;span class=&quot;s2&quot;&gt;&quot;/dev/sdb1&quot;&lt;/span&gt; successfully created.

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pvdisplay &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add the new PV to existing VG:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vgextend &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; centosvolume /dev/sdb1
  Wiping signatures on new PV /dev/sdb1.
  Archiving volume group &lt;span class=&quot;s2&quot;&gt;&quot;centosvolume&quot;&lt;/span&gt; metadata &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;seqno 2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
  Adding physical volume &lt;span class=&quot;s1&quot;&gt;&apos;/dev/sdb1&apos;&lt;/span&gt; to volume group &lt;span class=&quot;s1&quot;&gt;&apos;centosvolume&apos;&lt;/span&gt;
  Volume group &lt;span class=&quot;s2&quot;&gt;&quot;centosvolume&quot;&lt;/span&gt; will be extended by 1 new physical volumes
  Creating volume group backup &lt;span class=&quot;s2&quot;&gt;&quot;/etc/lvm/backup/centosvolume&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;seqno 3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
  Volume group &lt;span class=&quot;s2&quot;&gt;&quot;centosvolume&quot;&lt;/span&gt; successfully extended

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vgdisplay &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add the new to existing LV:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;lvextend &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--extents&lt;/span&gt; +100%FREE /dev/centosvolume/root
  Converted 100%FREE into at most 12799 physical extents.
  Archiving volume group &lt;span class=&quot;s2&quot;&gt;&quot;centosvolume&quot;&lt;/span&gt; metadata &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;seqno 3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
  Extending logical volume centosvolume/root to up to 89.05 GiB
  Size of logical volume centosvolume/root changed from &amp;lt;39.06 GiB &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;9999 extents&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; to 89.05 GiB &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;22798 extents&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
  Loading table &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;centosvolume-root &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;253:0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
  Suspending centosvolume-root &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;253:0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; with device flush
  Resuming centosvolume-root &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;253:0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
  Creating volume group backup &lt;span class=&quot;s2&quot;&gt;&quot;/etc/lvm/backup/centosvolume&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;seqno 4&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
  Logical volume centosvolume/root successfully resized.

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vgdisplay &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; Volume group &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
  VG Name               centosvolume
  System ID
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  4
  VG Access             &lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt;/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               89.05 GiB
  PE Size               4.00 MiB
  Total PE              22798
  Alloc PE / Size       22798 / 89.05 GiB
  Free  PE / Size       0 / 0
  VG UUID               1xOpAZ-6Idw-y2Oa-ELis-d338-8VgM-xyz

  &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; Logical volume &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
  LV Path                /dev/centosvolume/root
  LV Name                root
  VG Name                centosvolume
  LV UUID                2r1j88-PO5l-Fqrj-oeGz-T8Ez-TMSV-xyz
  LV Write Access        &lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt;/write
  LV Creation host, &lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;localhost, 2021-05-25 17:18:43 +0000
  LV Status              available
  &lt;span class=&quot;c&quot;&gt;# open                 1&lt;/span&gt;
  LV Size                89.05 GiB
  Current LE             22798
  Segments               2
  Allocation             inherit
  Read ahead sectors     auto
  - currently &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;to     8192
  Block device           253:0

  &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; Physical volumes &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
  PV Name               /dev/sda3
  PV UUID               NnWbVT-DtBY-XUMh-iFnD-JQZD-bXuJ-xyz
  PV Status             allocatable
  Total PE / Free PE    9999 / 0

  PV Name               /dev/sdb1
  PV UUID               yYxOYl-xxHv-EBOf-3jTw-O34v-BmmQ-xyz
  PV Status             allocatable
  Total PE / Free PE    12799 / 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From output above, we find the LV size is expanded to over 89 GiB. However, the XFS filesystem does not about this storage expansion. Let&apos;s do it again:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;
Filesystem                     Size  Used Avail Use% Mounted on
devtmpfs                       361M     0  361M   0% /dev
tmpfs                          403M     0  403M   0% /dev/shm
tmpfs                          403M   41M  362M  11% /run
tmpfs                          403M     0  403M   0% /sys/fs/cgroup
/dev/mapper/centosvolume-root   40G   11G   29G  27% /
/dev/sda2                     1014M  328M  687M  33% /boot
/dev/sda1                      100M  6.9M   93M   7% /boot/efi
tmpfs                           81M     0   81M   0% /run/user/1000

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;xfs_growfs /dev/centosvolume/root
meta-data&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/mapper/centosvolume-root &lt;span class=&quot;nv&quot;&gt;isize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;512    &lt;span class=&quot;nv&quot;&gt;agcount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4, &lt;span class=&quot;nv&quot;&gt;agsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2559744 blks
         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;                       &lt;span class=&quot;nv&quot;&gt;sectsz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4096  &lt;span class=&quot;nv&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2, &lt;span class=&quot;nv&quot;&gt;projid32bit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;                       &lt;span class=&quot;nv&quot;&gt;crc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1        &lt;span class=&quot;nv&quot;&gt;finobt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1, &lt;span class=&quot;nv&quot;&gt;sparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1, &lt;span class=&quot;nv&quot;&gt;rmapbt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;                       &lt;span class=&quot;nv&quot;&gt;reflink&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
data     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;                       &lt;span class=&quot;nv&quot;&gt;bsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4096   &lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;10238976, &lt;span class=&quot;nv&quot;&gt;imaxpct&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;25
         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;                       &lt;span class=&quot;nv&quot;&gt;sunit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0      &lt;span class=&quot;nv&quot;&gt;swidth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0 blks
naming   &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;version 2              &lt;span class=&quot;nv&quot;&gt;bsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4096   ascii-ci&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0, &lt;span class=&quot;nv&quot;&gt;ftype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
log      &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;internal log           &lt;span class=&quot;nv&quot;&gt;bsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4096   &lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4999, &lt;span class=&quot;nv&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2
         &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;                       &lt;span class=&quot;nv&quot;&gt;sectsz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4096  &lt;span class=&quot;nv&quot;&gt;sunit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 blks, lazy-count&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
realtime &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;none                   &lt;span class=&quot;nv&quot;&gt;extsz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4096   &lt;span class=&quot;nv&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0, &lt;span class=&quot;nv&quot;&gt;rtextents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
data blocks changed from 10238976 to 23345152

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;
Filesystem                     Size  Used Avail Use% Mounted on
devtmpfs                       361M     0  361M   0% /dev
tmpfs                          403M     0  403M   0% /dev/shm
tmpfs                          403M   41M  362M  11% /run
tmpfs                          403M     0  403M   0% /sys/fs/cgroup
/dev/mapper/centosvolume-root   90G   11G   79G  13% /
/dev/sda2                     1014M  328M  687M  33% /boot
/dev/sda1                      100M  6.9M   93M   7% /boot/efi
tmpfs                           81M     0   81M   0% /run/user/1000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the root filesystem is &lt;em&gt;ext4&lt;/em&gt;, then use &lt;em&gt;resize2fs&lt;/em&gt; instead.&lt;/p&gt;

&lt;h1 id=&quot;aws&quot;&gt;AWS&lt;/h1&gt;

&lt;p&gt;See &quot;AWS_EC2.docx&quot; and &quot;kong-on-aws.md&quot;.&lt;/p&gt;

&lt;h2 id=&quot;amazon-linux-extras&quot;&gt;amazon-linux-extras&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://aws.amazon.com/amazon-linux-2/faqs/#Amazon_Linux_Extras&quot;&gt;amazon-linux-extras&lt;/a&gt; is a mechanism to gurantee the stability of &lt;em&gt;fresh&lt;/em&gt; packages on Amazon Linux 2. Currently, only a small number of packages are supported.&lt;/p&gt;

&lt;p&gt;It&apos;s built upon YUM repository. Whenever a new package is installed through &apos;amazon-linux-extras&apos;, it add a corresponding YUM repository for the package.&lt;/p&gt;

&lt;p&gt;Firstly, make sure &lt;em&gt;amazon-linux-extras&lt;/em&gt; is installed.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;amazon-linux-extras

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;amazon-linux-extras

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;amazon-linux-extras &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Packages supported by &apos;amazon-linux-extras&apos; are called &lt;em&gt;topic&lt;/em&gt;. List available topics.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;amazon-linux-extras list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Enable a topic (YUM repository). The output will give you instructions how to install the topic.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Postgres14 client topic&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;amazon-linux-extras &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;postgresql14

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum repolist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Install a topic.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum clean metadata
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;postgresql14
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To make it easier, we can enable and install a topic at once.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;amazon-linux-extras &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;postgresql14
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;aliyun&quot;&gt;Aliyun&lt;/h1&gt;

&lt;p&gt;to-do&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Linux Time</title>
   <link href="/2021/03/03/linux-time/"/>
   <updated>2021-03-03T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2021/03/03/linux-time</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;VirtualBox guest OS relies on VirtualBox guest additions to synchronizes time with host. Hence leave this part after VirtualBox guest additions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In an operating system, the time (clock) is determined by four parts: time value, time standard, time zone, and Daylight Saving Time (DST) if applicable. Especially, RTC is just a bare value on board without any other information attached. It&apos;s the time managment tools that control time standard, time zone and DST.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;timedatectl&lt;/em&gt; is used to control system date and time while &lt;em&gt;hwclock&lt;/em&gt; is for hwardware time (RTC). The use of &lt;em&gt;timedatectl&lt;/em&gt; requires an active dbus. Therefore, it may not be possible to use this command under a &lt;em&gt;chroot&lt;/em&gt; (i.e. during installation). In such cases, you can revert back to the &lt;em&gt;hwclock&lt;/em&gt; command or wait for booting into the new system.&lt;/p&gt;

&lt;p&gt;As stated before, dual boot with Windows should set Linux system to treat RTC as &lt;em&gt;localtime&lt;/em&gt;. If this installation resides in virtual machine, then leave it default.&lt;/p&gt;

&lt;p&gt;Check time:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] timedatectl set-ntp true&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] timedatectl status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is an example of &lt;em&gt;timedatectl&lt;/em&gt; output:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                      Local time: Thu 2017-09-21 16:08:56 CEST
                  Universal time: Thu 2017-09-21 14:08:56 UTC
                        RTC time: Thu 2017-09-21 14:08:56
                       Time zone: Europe/Warsaw (CEST, +0200)
       System clock synchronized: yes
systemd-timesyncd.service active: yes
                 RTC in local TZ: no
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Don&apos;t be confused. Both &lt;em&gt;Local time&lt;/em&gt; and &lt;em&gt;Universal time&lt;/em&gt; are system time but with different time standards. The third one (RTC) is hardware time value. Obviously, RTC in this example is treated as Universal Time, which can be verified by the last line - RTC in local TZ: no&lt;/p&gt;

&lt;p&gt;Set timezone:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] ln -sf /usr/share/zoneinfo/Asia/Chongqing /etc/localtime (set system time zone manually)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] timedatectl set-timezone Asia/Chongqiong&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From the &lt;a href=&quot;https://www.zhstar.win/2015/09/10/lvm-luks-lvm/&quot;&gt;past experience&lt;/a&gt;, it&apos;s better to set time first and then time zone.&lt;/p&gt;

&lt;p&gt;Set time:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] hwclock [--systohc | --hctosys] [--utc | --localtime]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] timedatectl set-local-rtc 0/1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Tmux</title>
   <link href="/2020/10/24/tmux/"/>
   <updated>2020-10-24T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2020/10/24/tmux</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#overview&quot; id=&quot;markdown-toc-overview&quot;&gt;Overview&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configuration&quot; id=&quot;markdown-toc-configuration&quot;&gt;Configuration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#try-tmux&quot; id=&quot;markdown-toc-try-tmux&quot;&gt;Try Tmux&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tmux-sub-commands&quot; id=&quot;markdown-toc-tmux-sub-commands&quot;&gt;Tmux Sub-commands&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tmux-panes-synchronization&quot; id=&quot;markdown-toc-tmux-panes-synchronization&quot;&gt;Tmux Panes Synchronization&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tmux-command-key-bindings&quot; id=&quot;markdown-toc-tmux-command-key-bindings&quot;&gt;Tmux Command Key Bindings&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;overview&quot;&gt;Overview&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/andreyvit/2921703&quot;&gt;Tmux&lt;/a&gt; mainly comprises the server daemon and client. The server daemon manages multiple sessions. When a session is created, the server daemon is lauchned automatically. The client displays a session by &lt;em&gt;attach-session&lt;/em&gt;. The server and client are separate Tmux processes. They communicate through the socket under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$TMPDIR&lt;/code&gt;, like &quot;/tmp/tmux-xyz&quot;.&lt;/p&gt;

&lt;p&gt;A session can create multiple windows like terminal TABs. Each window occupy the whole screen area and can further be splitted into multiple panes (rectangle area on screen). Each window or pane is a separate pseudo terminal.&lt;/p&gt;

&lt;p&gt;We can regard Tmux Window and Pane as Emacs Frame and Window.&lt;/p&gt;

&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;/h1&gt;

&lt;p&gt;Tmux supports separate configurations to server, session, window or pane by &lt;em&gt;set-option&lt;/em&gt; (&lt;em&gt;set&lt;/em&gt;).&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set -s&lt;/code&gt; configures the server.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set&lt;/code&gt; configures a specific session.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set -w&lt;/code&gt; (alias &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setw&lt;/code&gt; ) configures a specific window.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set -p&lt;/code&gt; configures a specific pane. By default, pane inherits the configuration of window if there is not specific config.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Except the server, we can add extra &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; to configures the default options. Usually, we add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; in &lt;em&gt;~/.tmux.conf&lt;/em&gt;. The following is a sample:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/tmux.conf
# ~/.tmux.conf

# copy mode
#set -gw mode-keys vi
set -gw mode-keys emacs

# scrollback
set -g history-limit 100000
set -g mouse on

# bring ssh-agent to tmux
set -g update-environment &quot;SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION http_proxy HTTP_PROXY https_proxy HTTPS_PROXY ftp_proxy FTP_PROXY all_proxy ALL_PROXY no_proxy NO_PROXY&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To reflect the newest configuration file update, just &lt;a href=&quot;#tmux-sub-commands&quot;&gt;source it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another interesting repo &lt;a href=&quot;https://github.com/seebi/tmux-colors-solarized&quot;&gt;tmux-colors-solarized&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;try-tmux&quot;&gt;Try Tmux&lt;/h1&gt;

&lt;p&gt;Start new session:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tmux new-session &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; session-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To put Tmux background, we &lt;em&gt;detach&lt;/em&gt; by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-b d&lt;/code&gt; shortcut.&lt;/p&gt;

&lt;p&gt;List and kill session:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tmux &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tmux kill-session &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; session-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attatch to session:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# attach to latest detached session&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tmux a | at | attatch

&lt;span class=&quot;c&quot;&gt;# attach to a speciic session&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tmux a &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; session-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;tmux-sub-commands&quot;&gt;Tmux Sub-commands&lt;/h1&gt;

&lt;p&gt;Tmux has many sub-commands, like &lt;em&gt;new-session&lt;/em&gt;, &lt;em&gt;kill-session&lt;/em&gt; and &lt;em&gt;attach-session&lt;/em&gt; above. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux list-commands&lt;/code&gt; to show all supported sub-commands.&lt;/p&gt;

&lt;p&gt;Many sub-commands has built-in aliases, like &lt;em&gt;new&lt;/em&gt; for &lt;em&gt;new-session&lt;/em&gt;. We can also just type a few leading characters of a sub-command as long as no ambiguity incurred. For example, &lt;em&gt;attach-session&lt;/em&gt; can be expressed as just a single character &lt;em&gt;a&lt;/em&gt; or a simple word &lt;em&gt;att&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Once attached to a session, we can use key bindings to trigger sub-commands within the session. We call those key bindings &lt;em&gt;command key bindings&lt;/em&gt;. Command key bindings share the same prefix key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-b&lt;/code&gt;. For example, to create a window for the session, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-b c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can also manually input sub-commands within a session. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-b :&lt;/code&gt; to get into &lt;em&gt;command mode&lt;/em&gt;, and then input the sub-command. For instance, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-b : source-file ~/.tmux.conf&lt;/code&gt; reloads Tmux configuration on the fly. If you mis-typed a sub-commands, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-u&lt;/code&gt; and try again. To get out of command mode, just press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESC&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;tmux-panes-synchronization&quot;&gt;Tmux Panes Synchronization&lt;/h1&gt;

&lt;p&gt;Sometimes, we&apos;d like to run the same commands in multiple servers. For such requirements, we have ansible/fabric/pssh etc. Alternatively, tmux support &lt;a href=&quot;https://learn.redhat.com/t5/Platform-Linux/Using-tmux-to-execute-commands-on-servers-in-parallel/td-p/2200&quot;&gt;panes synchronization&lt;/a&gt;, namely synchronize the commands in one pane to others panes in the same window!&lt;/p&gt;

&lt;p&gt;To make use this feature, just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrol-b : setw synchronize-panes on/off&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;tmux-command-key-bindings&quot;&gt;Tmux Command Key Bindings&lt;/h1&gt;

&lt;p&gt;Apart from command mode, Tmux has the &lt;em&gt;copy mode&lt;/em&gt; by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrol-b [&lt;/code&gt;. Copy mode is used to navigate within shell screen in casef we don&apos;t have X (i.e. scroll up). Copy mode has its own key bingdings. By default, Tmux uses Emacs-like key bindings and gets out &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESC&lt;/code&gt;. You can change to Vi style and get out by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ENTER&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Check supported key bindings of copy mode by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux list-keys -T copy-mode&lt;/code&gt; (without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-T&lt;/code&gt;, list all Tmux key bindings). You will find that only part of Emacs or Vi key bindings are supported.&lt;/p&gt;

&lt;p&gt;The following are some general Tmux key bingdings and the corresponding sub-commands.&lt;/p&gt;

&lt;p&gt;Session operation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;: command mode
[ copy mode

s  list sessions
$  rename a session
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Window operation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;c  create window
w  list windows
n  next window
p  previous window
f  find window
&amp;amp;  kill window
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pane operation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;%  vertical split
&quot;  horizontal split

o  swap panes
x  kill pane
+  break pane into window (e.g. to select text by mouse to copy)
-  restore pane from window
⍽  space - toggle between layouts
q (pane numbers will show up on screen. When the numbers show up, press the relevant key, switching to that pane)
{ (Move the current pane left)
} (Move the current pane right)
z toggle pane zoom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Misc operation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;d  detach
t  big clock
?  list shortcuts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>macOS</title>
   <link href="/2020/10/12/macos/"/>
   <updated>2020-10-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2020/10/12/macos</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introductory&quot; id=&quot;markdown-toc-introductory&quot;&gt;Introductory&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#shortcuts&quot; id=&quot;markdown-toc-shortcuts&quot;&gt;Shortcuts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#package-installation&quot; id=&quot;markdown-toc-package-installation&quot;&gt;Package Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#general-setup&quot; id=&quot;markdown-toc-general-setup&quot;&gt;General Setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#shell-setup&quot; id=&quot;markdown-toc-shell-setup&quot;&gt;Shell Setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gh&quot; id=&quot;markdown-toc-gh&quot;&gt;gh&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#docker-desktop&quot; id=&quot;markdown-toc-docker-desktop&quot;&gt;Docker Desktop&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#homebrew&quot; id=&quot;markdown-toc-homebrew&quot;&gt;Homebrew&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#homebrew-tap&quot; id=&quot;markdown-toc-homebrew-tap&quot;&gt;Homebrew Tap&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#personal-tap&quot; id=&quot;markdown-toc-personal-tap&quot;&gt;Personal Tap&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#brew-edit&quot; id=&quot;markdown-toc-brew-edit&quot;&gt;brew edit&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#utm&quot; id=&quot;markdown-toc-utm&quot;&gt;UTM&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;introductory&quot;&gt;Introductory&lt;/h1&gt;

&lt;p&gt;macOS (Mac OS X or OS X) is a proprietary OS derived from Berkeley Software Distribution (BSD), and therefore is a Unix-like system. The main difference between macOS and other Unix-like distributions is that macOS is designed with &lt;em&gt;desktop&lt;/em&gt; for personal PC.&lt;/p&gt;

&lt;h1 id=&quot;shortcuts&quot;&gt;Shortcuts&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Screenshot
shift + command + 3/4/5

# Lock Screen
ctrl + command + q
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;package-installation&quot;&gt;Package Installation&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;#homebrew&quot;&gt;Homebrew&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;App Store.&lt;/li&gt;
  &lt;li&gt;Jamf Self Service.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;general-setup&quot;&gt;General Setup&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;touchpad tap with 1 click&lt;/li&gt;
  &lt;li&gt;Rime&lt;/li&gt;
  &lt;li&gt;Firefox&lt;/li&gt;
  &lt;li&gt;iTerm2&lt;/li&gt;
  &lt;li&gt;https://emacsformacosx.com/&lt;/li&gt;
  &lt;li&gt;ssh; load-ssh-agent&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;shell-setup&quot;&gt;Shell Setup&lt;/h1&gt;

&lt;p&gt;Set &quot;bashrc&quot; and &quot;bash_profile&quot; only after the following:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;coreutils
&lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;gdate &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type date

&lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;xz

brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;bash
&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; bash

&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;/etc/shells &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOL&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
&amp;gt; /opt/homebrew/bin/bash
&amp;gt; EOL

chsh -s /opt/homebrew/bin/bash

openssl version -a
brew install openssl@1.1
/opt/homebrew/Cellar/openssl&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\@&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;1.1/1.1.1o/bin/openssl version -a
PATH=&quot;/opt/homebrew/opt/openssl@1.1/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;

brew install tmux nmap gnupg

# for emacs markdown-preview
brew install pandoc
mkdir -p &quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;/.local/bin&quot;
PATH=&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;/.local/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;
ln -vs &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;pandoc&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt; &quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;/.local/bin/markdown&quot;

brew install libpq
PATH=&quot;/opt/homebrew/opt/libpq/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;

brew install btop
mkdir -p ~/.config/btop

PATH=&quot;/usr/local/go/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;/go/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;gh&quot;&gt;gh&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GITHUB_TOKEN&lt;/code&gt; and then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh auth login&lt;/code&gt; with the token.&lt;/p&gt;

&lt;h1 id=&quot;docker-desktop&quot;&gt;Docker Desktop&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/desktop/mac/install/&quot;&gt;Mac with Apple silicon&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;For compatibility, run &lt;em&gt;softwareupdate –install-rosetta&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;homebrew&quot;&gt;Homebrew&lt;/h1&gt;

&lt;p&gt;After installing &lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt;, we can optionally update &lt;a href=&quot;https://mirrors.tuna.tsinghua.edu.cn/help/homebrew/&quot;&gt;mirror&lt;/a&gt; to speed up package fetching.&lt;/p&gt;

&lt;p&gt;Everything of Homebrew is located under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(brew --prefix)&lt;/code&gt; (e.g., &lt;em&gt;/opt/homebrew&lt;/em&gt;). Especially, the prefix of a formulae is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew --prefix &amp;lt;formulae&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Get help info.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew commands

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;help install&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew config

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew doctor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;brew&lt;/em&gt; supports installing both CLI and GUI &lt;em&gt;formulae&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;CLI&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &amp;lt;formulae&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;GUI&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--cask&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &amp;lt;formulae&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cask&lt;/code&gt; is optinal and &lt;em&gt;brew cask&lt;/em&gt; is no longer a supported command.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sometimes, a formulate offers extra installation options (e.g. modules). For example, we can install OpenResty with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--with-slice&lt;/code&gt; to include the corresponding modules.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew options openresty
&lt;span class=&quot;nt&quot;&gt;--with-iconv&lt;/span&gt;
        Compile with ngx_http_iconv_module
&lt;span class=&quot;nt&quot;&gt;--with-postgresql&lt;/span&gt;
        Compile with ngx_http_postgres_module
&lt;span class=&quot;nt&quot;&gt;--with-slice&lt;/span&gt;
        Compile with ngx_http_slice_module
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Update formulae.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew update

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew outdated

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew upgrade
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Latest Homebrew uses API to install formulae, so it must fetch a file from &lt;a href=&quot;https://formulae.brew.sh/api/formula.json&quot;&gt;https://formulae.brew.sh/api/formula.json&lt;/a&gt;. The file size is over 18M and so may &lt;a href=&quot;https://github.com/Homebrew/discussions/discussions/4133&quot;&gt;report timeout issue&lt;/a&gt; as below.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;11:46:09 zachary@Zacharys-MacBook-Pro ~/workspace/resty-redis-cluster$ brew search openresty
curl: (28) Operation timed out after 5001 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5003 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5001 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5002 milliseconds with 0 bytes received
Error: Failure while executing; `/opt/homebrew/Library/Homebrew/shims/shared/curl --disable --cookie /dev/null --globoff --show-error --user-agent Homebrew/3.6.20-137-g12f3fb8\ \(Macintosh\;\ arm64\ Mac\ OS\ X\ 13.2\)\ curl/7.86.0 --header Accept-Language:\ en --fail --pr
ogress-bar --max-time 5 --retry 3 --location --remote-time --output /Users/zachary/Library/Caches/Homebrew/api/formula.json --time-cond /Users/zachary/Library/Caches/Homebrew/api/formula.json --compressed --silent https://formulae.brew.sh/api/formula.json` exited with 28.
 Here&apos;s the output:
curl: (28) Operation timed out after 5001 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5003 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5001 milliseconds with 0 bytes received
curl: (28) Operation timed out after 5002 milliseconds with 0 bytes received
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Either set a proxy or disable API by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HOMEBREW_NO_INSTALL_FROM_API=1&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;homebrew-tap&quot;&gt;Homebrew Tap&lt;/h2&gt;

&lt;p&gt;A &lt;em&gt;tap&lt;/em&gt; is a repository from where brew retrieves packages. By default, brew assumes a Github repository.&lt;/p&gt;

&lt;p&gt;Official tap list.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap
homebrew/cask
homebrew/core
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Say we have a tap named as &lt;em&gt;user/repo&lt;/em&gt;, the repository is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https://github.com/&amp;lt;user&amp;gt;/homebrew-&amp;lt;repo&amp;gt;&lt;/code&gt; (&lt;em&gt;homebrew&lt;/em&gt; prefix). Take &lt;em&gt;homebrew/core&lt;/em&gt; for example, the Github URL is &lt;a href=&quot;https://github.com/homebrew/homebrew-core&quot;&gt;https://github.com/homebrew/homebrew-core&lt;/a&gt;. The tap is cloned to local disk under directory &lt;em&gt;$(brew –repository)/Library/Taps&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We can add/remove 3rd-party taps on demand.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# assume Github repo&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap &amp;lt;user/repo&amp;gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap &amp;lt;user/homebrew-repo&amp;gt;

&lt;span class=&quot;c&quot;&gt;# Other repo with specific URL&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap &amp;lt;user/repo&amp;gt; &amp;lt;URL&amp;gt;

&lt;span class=&quot;c&quot;&gt;# remove&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew untap user/repo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once added, we can install formulae as in &lt;a href=&quot;#homebrew&quot;&gt;Homebrew&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, brew tries to install a formulae from official taps first. In case of duplicate formulae names among taps, We can install a formulae from a specific 3rd-party tap.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;user/repo/formulae
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;personal-tap&quot;&gt;Personal Tap&lt;/h3&gt;

&lt;p&gt;This section shows how to create a 3rd-party tap.&lt;/p&gt;

&lt;p&gt;Step 1. Create an empty Github repo as the personal tap, namely &lt;a href=&quot;https://github.com/outsinre/homebrew-wrk2&quot;&gt;homebrew-wrk2&lt;/a&gt;. The repo name must follow pattern &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;homebrew-&amp;lt;foo&amp;gt;&lt;/code&gt; (&lt;em&gt;homebrew&lt;/em&gt; prefix). We will put our formulaes into directory &quot;Formula&quot;.&lt;/p&gt;

&lt;p&gt;Now, let&apos;s add the personal tap to Homebrew.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap outsinre/wrk2

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap
homebrew/cask
homebrew/core
outsinre/wrk2

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;brew &lt;span class=&quot;nt&quot;&gt;--repository&lt;/span&gt; outsinre/wrk2&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git status

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git status
On branch master
Your branch is up to &lt;span class=&quot;nb&quot;&gt;date &lt;/span&gt;with &lt;span class=&quot;s1&quot;&gt;&apos;origin/master&apos;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

nothing to commit, working tree clean

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tree
&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
├── Formula
└── README.md

1 directory, 1 files

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap &lt;span class=&quot;nt&quot;&gt;--eval-all&lt;/span&gt; outsinre/wrk2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Step 2. Prepare code release.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git branch &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout wrk2-a64-support
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git diff &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt;~1

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout master
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git merge wrk2-a64-support

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git tag &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git tag &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; 1.0.0 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;release 1.0.0&quot;&lt;/span&gt; HEAD
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git tag &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git show &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; 1.0.0

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push origin &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push origin 1.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Go to Github and create release &lt;a href=&quot;https://github.com/outsinre/wrk2/archive/refs/tags/1.0.0.tar.gz&quot;&gt;1.0.0&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Step 3. Create formulae.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew create &lt;span class=&quot;nt&quot;&gt;--tap&lt;/span&gt; outsinre/wrk2 https://github.com/outsinre/wrk2/archive/refs/tags/1.0.0.tar.gz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Command above puts the newly formulae into our local personal tap &lt;em&gt;outsinre/wrk2&lt;/em&gt;. If we don&apos;t offer the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--tap&lt;/code&gt; option, the formulae would, by default, be placed into the official tap (i.e. &lt;em&gt;homebrew/core&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;An editor is popped up to edit the new formulae. Please follow &lt;a href=&quot;https://github.com/Homebrew/homebrew-core/blob/master/Formula/wrk.rb&quot;&gt;wrk.rb&lt;/a&gt; and &lt;a href=&quot;https://github.com/jabley/homebrew-wrk2&quot;&gt;wrk2.rb&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Step 4. Audit the new formulae&apos;s adherence to Homebrew house style.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# validate tap&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap &lt;span class=&quot;nt&quot;&gt;--eval-all&lt;/span&gt; outsinre/wrk2

&lt;span class=&quot;c&quot;&gt;# validate formula&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew audit &lt;span class=&quot;nt&quot;&gt;--strict&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--online&lt;/span&gt; outsinre/wrk2/wrk2

&lt;span class=&quot;c&quot;&gt;# validate formula more strictly&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew audit &lt;span class=&quot;nt&quot;&gt;--new&lt;/span&gt; outsinre/wrk2/wrk2

outsinre/wrk2/wrk2:
  &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 2: col 9: Description shouldn&lt;span class=&quot;s1&quot;&gt;&apos;t start with an article.
  * 7: col 3: `license` (line 7) should be put before `head` (line 6)
  * 24: col 12: Ambiguous splat operator. Parenthesize the method arguments if it&apos;&lt;/span&gt;s surely a splat operator, or add a whitespace to the right of the &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;it should be a multiplication.
Error: 3 problems &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;1 formula detected
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Update formulae according to audit results.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;brew &lt;span class=&quot;nt&quot;&gt;--repository&lt;/span&gt; outsinre/wrk2&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
~ /opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nano &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; wrk2.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Step 5. Sync local tap with Github.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;brew &lt;span class=&quot;nt&quot;&gt;--repository&lt;/span&gt; outsinre/wrk2&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git status
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git add &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;add formulae wrk2&quot;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/opt/homebrew/Library/Taps/outsinre/homebrew-wrk2&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push origin &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Step 6. Install the new formulae.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;outsinre/wrk2/wrk2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If a new release is out. We should firstly backup and remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(brew --repository outsinre/wrk2)/Formula/wrk2.rb&lt;/code&gt; and then repeat steps 2 ~ 6 above. Mostly, we only need to update the &lt;em&gt;sha256&lt;/em&gt; and &lt;em&gt;url&lt;/em&gt; part.&lt;/p&gt;

&lt;p&gt;However, we can also install the from the latest source code if &lt;em&gt;head&lt;/em&gt; is defined the formulae.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--HEAD&lt;/span&gt; outsinre/wrk2/wrk2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.brew.sh/Formula-Cookbook&quot;&gt;Formula-Cookbook&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://publishing-project.rivendellweb.net/creating-and-running-your-own-homebrew-tap/&quot;&gt;Creating and running your own Homebrew tap&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://betterprogramming.pub/a-step-by-step-guide-to-create-homebrew-taps-from-github-repos-f33d3755ba74&quot;&gt;Step by step guide to create Homebrew tap&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;brew-edit&quot;&gt;brew edit&lt;/h2&gt;

&lt;p&gt;Sometimes, we want to change (version, url, etc.) formulas locally in place. For example, we do not want to wait for upstream update.&lt;/p&gt;

&lt;p&gt;The following steps demostrate how to upgrade OpenResty version locally.&lt;/p&gt;

&lt;p&gt;Remove the formulae in advance.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew uninstall openresty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Edit formula &quot;openresty&quot; in tap &quot;openresty/brew&quot;. We change &quot;VERSION&quot; from &quot;1.21.4.1&quot; ro &quot;1.21.4.2rc1&quot;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap
openresty/brew

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew edit openresty/brew/openresty
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; VERSION &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1.21.4.2rc1&quot;&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nt&quot;&gt;--repository&lt;/span&gt; openresty/brew
/opt/homebrew/Library/Taps/openresty/homebrew-brew

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;brew &lt;span class=&quot;nt&quot;&gt;--repository&lt;/span&gt; openresty/brew&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

15:12:31 zachary@Zacharys-MacBook-Pro /opt/homebrew/Library/Taps/openresty/homebrew-brew&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git diff
diff &lt;span class=&quot;nt&quot;&gt;--git&lt;/span&gt; a/Formula/openresty.rb b/Formula/openresty.rb
index f25142d..46262e2 100644
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; a/Formula/openresty.rb
+++ b/Formula/openresty.rb
@@ &lt;span class=&quot;nt&quot;&gt;-3&lt;/span&gt;,7 +3,7 @@ require &lt;span class=&quot;s1&quot;&gt;&apos;etc&apos;&lt;/span&gt;
 class Openresty &amp;lt; Formula
   desc &lt;span class=&quot;s2&quot;&gt;&quot;Scalable Web Platform by Extending NGINX with Lua&quot;&lt;/span&gt;
   homepage &lt;span class=&quot;s2&quot;&gt;&quot;https://openresty.org&quot;&lt;/span&gt;
-  VERSION &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1.21.4.1&quot;&lt;/span&gt;.freeze
+  VERSION &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1.21.4.2rc1&quot;&lt;/span&gt;.freeze
   revision 2
   url &lt;span class=&quot;s2&quot;&gt;&quot;https://openresty.org/download/openresty-#{VERSION}.tar.gz&quot;&lt;/span&gt;
   sha256 &lt;span class=&quot;s2&quot;&gt;&quot;0c5093b64f7821e85065c99e5d4e6cc31820cfd7f37b9a0dec84209d87a2af99&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, we should also update &quot;sha256&quot; of the new version. We can manually download the tarball and calculate &quot;sha256&quot; locally. Alternatively, we let brew calculate it as follows.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew fetch &lt;span class=&quot;nt&quot;&gt;--build-from-source&lt;/span&gt; openresty/brew/openresty

&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; Fetching openresty from openresty/brew
&lt;span class=&quot;o&quot;&gt;==&amp;gt;&lt;/span&gt; Downloading https://openresty.org/download/openresty-1.21.4.2rc1.tar.gz

Downloaded to: /Users/zachary/Library/Caches/Homebrew/downloads/ad1460c199727f56f390f2dfd99817dc8d6bdedd539e3b8fac4efa6eb0519a27--openresty-1.21.4.2rc1.tar.gz
SHA256: ee96bbcf119abe5f1fc90461dd4674bd9397aa3db5544139578d9ace81983fdb
Warning: Formula reports different sha256: 0c5093b64f7821e85065c99e5d4e6cc31820cfd7f37b9a0dec84209d87a2af99
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The new &quot;sha256&quot; is printed to stdout. Let&apos;s update accordingly.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew edit openresty/brew/openresty

15:16:25 zachary@Zacharys-MacBook-Pro /opt/homebrew/Library/Taps/openresty/homebrew-brew&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git diff
diff &lt;span class=&quot;nt&quot;&gt;--git&lt;/span&gt; a/Formula/openresty.rb b/Formula/openresty.rb
index f25142d..afdf97c 100644
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt; a/Formula/openresty.rb
+++ b/Formula/openresty.rb
@@ &lt;span class=&quot;nt&quot;&gt;-3&lt;/span&gt;,10 +3,10 @@ require &lt;span class=&quot;s1&quot;&gt;&apos;etc&apos;&lt;/span&gt;
 class Openresty &amp;lt; Formula
   desc &lt;span class=&quot;s2&quot;&gt;&quot;Scalable Web Platform by Extending NGINX with Lua&quot;&lt;/span&gt;
   homepage &lt;span class=&quot;s2&quot;&gt;&quot;https://openresty.org&quot;&lt;/span&gt;
-  VERSION &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1.21.4.1&quot;&lt;/span&gt;.freeze
+  VERSION &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1.21.4.2rc1&quot;&lt;/span&gt;.freeze
   revision 2
   url &lt;span class=&quot;s2&quot;&gt;&quot;https://openresty.org/download/openresty-#{VERSION}.tar.gz&quot;&lt;/span&gt;
-  sha256 &lt;span class=&quot;s2&quot;&gt;&quot;0c5093b64f7821e85065c99e5d4e6cc31820cfd7f37b9a0dec84209d87a2af99&quot;&lt;/span&gt;
+  sha256 &lt;span class=&quot;s2&quot;&gt;&quot;ee96bbcf119abe5f1fc90461dd4674bd9397aa3db5544139578d9ace81983fdb&quot;&lt;/span&gt;

   option &lt;span class=&quot;s2&quot;&gt;&quot;with-postgresql&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;Compile with ngx_http_postgres_module&quot;&lt;/span&gt;
   option &lt;span class=&quot;s2&quot;&gt;&quot;with-iconv&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;Compile with ngx_http_iconv_module&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can validate the update according to instructions in section &lt;a href=&quot;#personal-tap&quot;&gt;Personal Tap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If everything is ok, we install the new version.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;openresty/brew/openresty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;One side effect is that, local edits may conflicts with future upstream updates!&lt;/p&gt;

&lt;h1 id=&quot;utm&quot;&gt;UTM&lt;/h1&gt;

&lt;p&gt;UTM is an open source VMM supporting iOS and OSX. What is more, it supports Apple ARM64!&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://mac.getutm.app/&quot;&gt;Installation&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mac.getutm.app/gallery/&quot;&gt;Gallery&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;After installation, remove and re-add the USB (DVD) drive, otherwise the boot menu break from time to time.&lt;/li&gt;
  &lt;li&gt;Follow tutorial &lt;a href=&quot;https://mac.getutm.app/gallery/ubuntu-20-04&quot;&gt;UTM Ubuntu 20.04&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;UTM uses &lt;em&gt;davfs2&lt;/em&gt; to share files with host OS. Here is setup on guest OS:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# clipboard sharing, mouse integration&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;spice-vdagent

&lt;span class=&quot;c&quot;&gt;# file shareing&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;spice-webdavd davfs2

&lt;span class=&quot;c&quot;&gt;# group&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;usermod &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-G&lt;/span&gt; davfs2 kong
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;reboot

&lt;span class=&quot;c&quot;&gt;# /etc/fstab&lt;/span&gt;
http://127.0.0.1:9843   /media/webdav   davfs   _netdev,noauto,noexec,user,uid&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kong,gid&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;kong    0       0

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /media/webdav
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount /media/webdav
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-al&lt;/span&gt; ~/.davfs2/

&lt;span class=&quot;c&quot;&gt;# auto password&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ~/.davfs2/secrets&lt;/span&gt;
/media/webdav   kong    kong

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;umount /media/wevdav
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount /media/wevdav
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If just use Web browser (e.g. VM has X), then no need to install &lt;em&gt;davfs2&lt;/em&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>TeXLive</title>
   <link href="/2020/08/11/texlive/"/>
   <updated>2020-08-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2020/08/11/texlive</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#texmf&quot; id=&quot;markdown-toc-texmf&quot;&gt;texmf&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#overview&quot; id=&quot;markdown-toc-overview&quot;&gt;Overview&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#os-package-manager&quot; id=&quot;markdown-toc-os-package-manager&quot;&gt;OS Package Manager&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#centos&quot; id=&quot;markdown-toc-centos&quot;&gt;CentOS&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#archlinux&quot; id=&quot;markdown-toc-archlinux&quot;&gt;archlinux&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#net-installer&quot; id=&quot;markdown-toc-net-installer&quot;&gt;Net Installer&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#dvd-iso&quot; id=&quot;markdown-toc-dvd-iso&quot;&gt;DVD ISO&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#preparation&quot; id=&quot;markdown-toc-preparation&quot;&gt;Preparation&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#installation-from-iso&quot; id=&quot;markdown-toc-installation-from-iso&quot;&gt;Installation from ISO&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#tex-environment-variables-for-unix&quot; id=&quot;markdown-toc-tex-environment-variables-for-unix&quot;&gt;TeX environment variables for Unix&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#check-installation-scheme&quot; id=&quot;markdown-toc-check-installation-scheme&quot;&gt;Check Installation Scheme&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#update&quot; id=&quot;markdown-toc-update&quot;&gt;Update&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#additional-packages-and-fonts&quot; id=&quot;markdown-toc-additional-packages-and-fonts&quot;&gt;Additional Packages and Fonts&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;texmf&quot;&gt;&lt;a href=&quot;https://tex.stackexchange.com/a/77726&quot;&gt;texmf&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;You will see name &lt;em&gt;texmf&lt;/em&gt; everywhere. It stands for TEX and METAFONT (an old language Knuth used to design fonts).&lt;/p&gt;

&lt;h1 id=&quot;overview&quot;&gt;&lt;a href=&quot;http://tug.org/texlive/doc/texlive-en/texlive-en.html&quot;&gt;Overview&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;To setup a TeX system, you need to do finish two tasks:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install TeX by a distribution, like TeXLive, MiKTeX etc.&lt;/li&gt;
  &lt;li&gt;Manage TeX system by built-in &lt;em&gt;texconﬁg&lt;/em&gt; or &lt;em&gt;tlmgr&lt;/em&gt; of TeXLive, the later of which is far more powerful.
    &lt;ol&gt;
      &lt;li&gt;Install, update, uninstall, backup individual TeX packages.&lt;/li&gt;
      &lt;li&gt;Change installation options like paper size and source location.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;You can regard &lt;em&gt;tlmgr&lt;/em&gt; as package manager similar to &lt;em&gt;dnf&lt;/em&gt;, &lt;em&gt;emerge&lt;/em&gt; etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Leave TeX installation in a standalone directory. Do not spread it across the LFS.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;h2 id=&quot;os-package-manager&quot;&gt;OS Package Manager&lt;/h2&gt;

&lt;p&gt;Installation from package manager is a minimal install and may lack some fundamental TeX packages (error-prone). So, it&apos;s not recommended.&lt;/p&gt;

&lt;h3 id=&quot;centos&quot;&gt;CentOS&lt;/h3&gt;

&lt;p&gt;By default, the XeTeX engin is not installed. Hence, put it on command line too:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;texlive texlive-xetex
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;archlinux&quot;&gt;archlinux&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; texlive-most texlive-lang biber
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;net-installer&quot;&gt;Net Installer&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://tug.org/texlive/acquire-netinstall.html&quot;&gt;Net Installer&lt;/a&gt; is recommended by TeXLive, but limited by local bandwidth and is prone to network abrupt.&lt;/p&gt;

&lt;p&gt;The advantage by net installer is you get the latest updates.&lt;/p&gt;

&lt;h2 id=&quot;dvd-iso&quot;&gt;DVD ISO&lt;/h2&gt;

&lt;p&gt;It&apos;s recommended to do a &lt;em&gt;full&lt;/em&gt; install from &lt;a href=&quot;https://mirror.lzu.edu.cn/CTAN/systems/texlive/Images/texlive.iso&quot;&gt;ISO&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;ISO contains everything needed to run TeX system and is a fully tested release.&lt;/p&gt;

&lt;h3 id=&quot;preparation&quot;&gt;Preparation&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Spare at least 10G disk space.&lt;/li&gt;
  &lt;li&gt;Download the ISO (around 5G).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;texmf&lt;/em&gt; trees shoulf follow &lt;a href=&quot;https://tug.org/tds&quot;&gt;TeX Directory Structure (TDS)&lt;/a&gt;. A tree usually includes the following top-level sub-directories:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tex/
fonts/
metafonts/
metapost/
bibtex/
scripts/
doc/
source/
implementation/
program/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Of of all the top-level sub-directories, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tex/&lt;/code&gt; is where TeX macros located, with pathname as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;texmf/tex/format/package/&lt;/code&gt;. &lt;em&gt;format&lt;/em&gt; can be &lt;em&gt;amstex&lt;/em&gt;, &lt;em&gt;latex&lt;/em&gt;, &lt;em&gt;plain&lt;/em&gt;, &lt;em&gt;texinfo&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Various &lt;a href=&quot;http://www.tug.org/texlive/doc/texlive-en/texlive-en.html#x1-110002.3&quot;&gt;texmf trees&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;TEXMF, TEXDIR, TEXMFROOT (TeXLive release):
  /usr/local/texlive/{2020,2021}

TEXMFDIST, TEXMFMAIN (official TeX tree):
  /usr/local/texlive/2020/texmf-dist

TEXMFLOCAL (system-wide customized tree):
  /usr/local/texlive/texmf-local
TEXMFHOME (per-user customized tree):
  ~/texmf

TEXMFSYSVAR (system-wide runtime cache data):
  /usr/local/texlive/2020/texmf-var
TEXMFVAR (per-user runtime cache data):
  ~/.texlive2020/texmf-var

TEXMFSYSCONFIG (system-wide modiﬁed conﬁguration data):
  /usr/local/texlive/2020/texmf-config
TEXMFCONFIG (per-user modiﬁed conﬁguration data):
  ~/.texlive2020/texmf-config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;These TeX variables can be overriden by system environment variables like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TEXLIVE_INSTALL_PREFIX&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TEXLIVE_INSTALL_TEXDIR&lt;/code&gt;. Check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;install-tl --help&lt;/code&gt; for details.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;installation-from-iso&quot;&gt;Installation from ISO&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /mnt/iso; cd /mnt/iso&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# mount /path/to/texlive.iso .&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# text mode&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# per ./install-tl&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# GUI mode&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# per ./install-tl -gui&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Leave the default settings (full installation) if you dunno what you are doing. There is an option:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;create symlinks in standard directories&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Please leave it it uncheck, which otherwise may ruin your system &lt;em&gt;bin&lt;/em&gt; directories.&lt;/p&gt;

&lt;p&gt;It may take half an hour to complete the installation.&lt;/p&gt;

&lt;h3 id=&quot;tex-environment-variables-for-unix&quot;&gt;TeX environment variables for Unix&lt;/h3&gt;

&lt;p&gt;There may exist multiple TeX distributions installed alongside. So, it&apos;s better to create a current version symlink.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# cd /usr/local/texlive/&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# ln -sv 2020 current &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Mainly, adjust the search path.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PATH=/usr/local/texlive/current/bin/x86_64-linux:$PATH; export PATH
MANPATH=/usr/local/texlive/current/texmf-dist/doc/man:$MANPATH; export MANPATH
INFOPATH=/usr/local/texlive/current/texmf-dist/doc/info:$INFOPATH; export INFOPATH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;check-installation-scheme&quot;&gt;Check Installation Scheme&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;tlmgr&lt;/em&gt; will reveal everythin about the setup.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# tlmgr --help&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# tlmgr conf&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# kpsewhich -a texmf.cnf&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# kpsewhich -var-value=TEXMFHOME&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# kpsewhich foo.sty&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# kpsewhich bar.cls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;update&quot;&gt;Update&lt;/h1&gt;

&lt;p&gt;It is highly recommened &lt;strong&gt;not&lt;/strong&gt; to update TeX distribution in place. Instead, you&apos;d better install a new distribution version. Alternatively, please update or install individual packages into &lt;a href=&quot;#additional-packages-and-fonts&quot;&gt;TEXMFLOCAL or TEXMFHOME&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Where should we get updates from?&lt;/p&gt;

    &lt;p&gt;By default, the&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;after install, set CTAN as source for package updates&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;option is checked upon installation.&lt;/p&gt;

    &lt;p&gt;But we can manually set the update repository afterwards:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ # tlmgr option repository http://mirror.ctan.org/systems/texlive/tlnet
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This tells tlmgr to use a nearby CTAN mirror for future updates.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://tug.org/texlive/doc/texlive-en/texlive-en.html#x1-450005.2&quot;&gt;How to update&lt;/a&gt;?&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# GUI
~ # tlmgr -gui

# Text
~ # tlmgr update -all -dry-run
~ # tlmgr update -list

~ # tlmgr update -all
~ # tlmgr -repository /local/mirror/tlnet install collection-xetex

~ # tlmgr show collection-latexextra
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;additional-packages-and-fonts&quot;&gt;Additional Packages and Fonts&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;http://www.tug.org/texlive/doc/texlive-en/texlive-en.html#x1-360003.4.6&quot;&gt;Additional new or updated&lt;/a&gt; packages and fonts are expected to be in TEXMFLOCAL (system-wide) or TEXMFHOME (per-user, RECOMMENDED), independent of TeX distributions.&lt;/p&gt;

&lt;p&gt;For changes under TEXMFLOCAL, we should &lt;a href=&quot;https://tex.stackexchange.com/q/476537&quot;&gt;update the search path for Kpathsea&lt;/a&gt;, as TEXMFLOCAL is prefixed with double &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!!&lt;/code&gt;in &lt;em&gt;texmf.cnf&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ # mktexlsr [/usr/local/telive/texmf-local/]
# -or-
~ # mktexlsr [$(kpsewhich -var-value=TEXMFLOCAL)]

~ # kpsewhich foobar.sty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;mktexls&lt;/em&gt; acutally just creates a file named &lt;em&gt;ls-R&lt;/em&gt; under the specified directory.&lt;/p&gt;

    &lt;p&gt;Without the directory argument, &lt;em&gt;mktexlsr&lt;/em&gt; tries updates all &lt;em&gt;ls-R&lt;/em&gt; for the installation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You can also use &lt;em&gt;texhash&lt;/em&gt; as it is just a symlink to &lt;em&gt;mktexlsr&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Kickstart</title>
   <link href="/2020/07/25/kickstart/"/>
   <updated>2020-07-25T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2020/07/25/kickstart</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#kickstart&quot; id=&quot;markdown-toc-kickstart&quot;&gt;Kickstart&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#outline&quot; id=&quot;markdown-toc-outline&quot;&gt;Outline&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#preparation&quot; id=&quot;markdown-toc-preparation&quot;&gt;Preparation&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#procedures&quot; id=&quot;markdown-toc-procedures&quot;&gt;Procedures&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#1-mount-official-78-iso-image&quot; id=&quot;markdown-toc-1-mount-official-78-iso-image&quot;&gt;1 Mount Official 7.8 ISO image&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#2-customize-iso-contents&quot; id=&quot;markdown-toc-2-customize-iso-contents&quot;&gt;2 Customize ISO Contents&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#3-customize-compsxml&quot; id=&quot;markdown-toc-3-customize-compsxml&quot;&gt;3 Customize comps.xml&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#4-generate-kscfg&quot; id=&quot;markdown-toc-4-generate-kscfg&quot;&gt;4 Generate ks.cfg&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#5-customize-boot-menu&quot; id=&quot;markdown-toc-5-customize-boot-menu&quot;&gt;5 Customize Boot Menu&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#7-generate-repodata&quot; id=&quot;markdown-toc-7-generate-repodata&quot;&gt;7 Generate repodata&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#8-generate-new-iso-image&quot; id=&quot;markdown-toc-8-generate-new-iso-image&quot;&gt;8 Generate new ISO image&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#9-hybrid-iso&quot; id=&quot;markdown-toc-9-hybrid-iso&quot;&gt;9 Hybrid ISO&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#10-embed-md5-into-iso&quot; id=&quot;markdown-toc-10-embed-md5-into-iso&quot;&gt;10 Embed MD5 into ISO&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#install-new-iso-image&quot; id=&quot;markdown-toc-install-new-iso-image&quot;&gt;Install New ISO Image&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#reference&quot; id=&quot;markdown-toc-reference&quot;&gt;Reference&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#todos&quot; id=&quot;markdown-toc-todos&quot;&gt;Todos&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;kickstart&quot;&gt;Kickstart&lt;/h1&gt;

&lt;h2 id=&quot;outline&quot;&gt;Outline&lt;/h2&gt;

&lt;p&gt;Kickstart 支持在内网设定装机服务器，所有需要装机的设备连接服务器，实现从网络启动，实现自动化装机。本文介绍简化版用例，基于 Kickstart 定制 ISO 文件，实现自动装机。&lt;/p&gt;

&lt;p&gt;主要定制包括：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;自动装机。&lt;/li&gt;
  &lt;li&gt;增、删、改内置 rpm 包。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;定制系统参数，如 DNS, 网络、启动服务等。&lt;/p&gt;

    &lt;p&gt;这部分在主系统装完后操作。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;装完自动重启。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;preparation&quot;&gt;Preparation&lt;/h2&gt;

&lt;p&gt;所有的操作在同版本 CentOS 下进行。例如要定制 CentOS 7.8 的 ISO, 则最好在 CentOS 7.8 系统下操作。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;rsync createrepo genisoimage isomd5sum pykickstart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;genisoimage 替换老旧的 mkisofs.&lt;/li&gt;
  &lt;li&gt;isomd5sum (implantisomd5) 用于给 ISO 打 md5 值。&lt;/li&gt;
  &lt;li&gt;pykickstart (ksvalidator) 用于验证 ks.cfg 语法。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;procedures&quot;&gt;Procedures&lt;/h2&gt;

&lt;h3 id=&quot;1-mount-official-78-iso-image&quot;&gt;1 Mount Official 7.8 ISO image&lt;/h3&gt;

&lt;p&gt;挂载官方 ISO 文件。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lsblk
ll /dev/cdrom

&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /mnt&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;cdrom,iso&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
mount /dev/cdrom /mnt/cdrom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-customize-iso-contents&quot;&gt;2 Customize ISO Contents&lt;/h3&gt;

&lt;p&gt;定制 ISO 内容。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /mnt/iso
rsync &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; /mnt/cdrom /mnt/iso

&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /mnt/iso/repodata/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /path/to/my-pkg.rpm /mnt/iso/Packages/
yum &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--downloadonly&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--downloaddir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/mnt/iso/Packages/ pkg1 pkg2 pkg3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;清空 repodata 目录，后面会重建。&lt;/li&gt;
  &lt;li&gt;本例主要添加额外安装包到 Packages 目录。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;3-customize-compsxml&quot;&gt;3 Customize comps.xml&lt;/h3&gt;

&lt;p&gt;对 ISO 改动后，需要重新生成 comps.xml. comps.xml 是 XML 文件，有 2 个大 tag, 即 &apos;group&apos; 与 &apos;environment&apos;. group 定义 rpm 包的集合，里面的 rpm 包紧密相关，而 environment 是 group 的集合，里面包含的 group 全部安装进系统。例如，CentOS 的 &apos;minimal&apos; environment 里，默认只有 core 这个 group. 在系统中通过 &apos;dnf group install&apos; 安装 group 与 environment 集合。&lt;/p&gt;

&lt;p&gt;本例中，主要是往 minimal environment 里增加内置 rpm 包，所以需要把这些新的 rpm 包名加到 comps.xml 里。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /mnt/iso/douyu
&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /mnt/cdrom/repodata/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;c7-minimal-x86_64-comps.xml /mnt/iso/douyu/c7-minimal-x86_64-comps.xml

&lt;span class=&quot;c&quot;&gt;# emacs /mnt/iso/douyu/c7-minimal-x86_64-comps.xml&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#      &amp;lt;packagereq type=&quot;default&quot;&amp;gt;my-pkg&amp;lt;/packagereq&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#      &amp;lt;packagereq type=&quot;default&quot;&amp;gt;pkg1&amp;lt;/packagereq&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#      &amp;lt;packagereq type=&quot;default&quot;&amp;gt;pkg2&amp;lt;/packagereq&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#      &amp;lt;packagereq type=&quot;optional&quot;&amp;gt;pkg3&amp;lt;/packagereq&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;comps.xml 定制说明：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;添加 pkg.rpm 包时，需同时添加其依赖包，否则无法安装。&lt;/li&gt;
  &lt;li&gt;为添加的 rpm 包定义 group.
    &lt;ol&gt;
      &lt;li&gt;可以直接修改 &apos;core&apos; group.&lt;/li&gt;
      &lt;li&gt;可以仿照 core 自定义一个新 group.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;本例是直接修改 core. 如果是自定义 group, 则在 environment 环境后，添加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;groupid&amp;gt;my-group&amp;lt;/groupid&amp;gt;&lt;/code&gt;, 表示把自己的 group 包括进对应的 environment 里，以便安装。没有添加进 environment 里的 group 是不会安装的。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;为新 rpm 包添加 &apos;packagereq&apos; tag.&lt;/p&gt;

    &lt;p&gt;type 参数为 &apos;default&apos; 表示默认会安装（默认打勾），&apos;mandatory&apos; 表示必须要安装，不可取消打勾，&apos;optional&apos; 表示可选安装（默认末打勾）。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;4-generate-kscfg&quot;&gt;4 Generate ks.cfg&lt;/h3&gt;

&lt;p&gt;Kickstart 配制文件生成方案：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Kickstart 提供了图形界面的配制工具 system-config-kickstart, 可先用图形界面生成、更新 ks.cfg 模版，再作细节优化。&lt;/li&gt;
  &lt;li&gt;先用图形界面手动安装一遍操作系统。安装完毕，anaconda 会在 /root 下生成 anaconda-ks.cfg 的文件，记录本次手动安装过程所对应的 Kickstart 配制文件。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;两种方案中，前者可定制的参数比较全面，后者因为是实操作，更可靠。需要注意的是，如果第 2 种方法是在 VM 里手动安装，则可能存在一些参数与实际物理机安装不同。例如 /root 下的 anaconda-ks.cfg 文件里，往往在分区参数上，分区大小是固定的（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;part / --fstype=&quot;xfs&quot; --size=7167&lt;/code&gt;），需要改成自适应模式。&lt;/p&gt;

&lt;p&gt;生成 ks.cfg 后，先验证语法：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /mnt/iso/douyu
&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /path/to/ks.cfg /mnt/iso/douyu/

ksvalidator /mnt/iso/douyu/ks.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;ks.cfg 主要作用是代替手动安装的步骤，例如语言、键盘、时区、分区等。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%post ... %end&lt;/code&gt; 表示安装完毕，重启前的收尾工作。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%packages ... %end&lt;/code&gt; 指定安装需要安装的包。
    &lt;ol&gt;
      &lt;li&gt;以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@^&lt;/code&gt; 开头的表示安装 environment 里所有的 group.&lt;/li&gt;
      &lt;li&gt;以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; 并开表示单独安装某个 group 里的包。&lt;/li&gt;
      &lt;li&gt;直接以包名开头，表示安装某个包。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ks.cfg 模版参考 &apos;7.8\7.8-ks_auto3.cfg&apos;.&lt;/p&gt;

&lt;h3 id=&quot;5-customize-boot-menu&quot;&gt;5 Customize Boot Menu&lt;/h3&gt;

&lt;p&gt;生成 ks.cfg 后，修改启动项模版 legacy BIOS isolinux.cfg 与 EFI grub.cfg.&lt;/p&gt;

&lt;p&gt;Legacy BIOS 启动：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# isolinux/isolinux.cfg

timeout 60

label linux
  menu label ^KS Install CentOS 7.8
  kernel vmlinuz
  menu default
  append initrd=initrd.img inst.stage2=hd:LABEL=CentOS7 inst.ks=cdrom:/douyu/ks.cfg quiet
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;超时改成 60 ms 而非默认的 600 ms.&lt;/li&gt;
  &lt;li&gt;主要修改地方是，指定 ks.cfg 位置。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;inst.stage2 是安装完毕后，硬盘启动位置 label&lt;/p&gt;

    &lt;p&gt;&apos;hd:LABEL=&apos; 全部改成统一的字符串，可随意设定，但 &lt;strong&gt;MUST be the SAME AS THAT of genisoimage -V BELLOW&lt;/strong&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;inst.ks 是 Kickstart 加载配制文件的位置。&lt;/p&gt;

    &lt;p&gt;本例中，ks.cfg 直接存于 ISO 文件，实际中可放于其它地方，如 U 盘、硬盘分区、网络地址等。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;把此 menu 改成默认的，即加 &apos;menu default&apos; 行。同时注释其它 menu 的 &apos;menu default&apos; 行。官方 ISO 的 &apos;menu default&apos; 在 &apos;label check&apos; menu 上。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;参考 &apos;7.8\isolinux.cfg&apos;.&lt;/p&gt;

&lt;p&gt;EFI grub.cfg 启动：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# EFI/BOOT/grub.cfg

set default=&quot;0&quot;

menuentry &apos;KS Install CentOS 7&apos; --class fedora --class gnu-linux --class gnu --class os {
	linuxefi /images/pxeboot/vmlinuz inst.stage2=hd:LABEL=CentOS7 inst.ks=cdrom:/douyu/ks.cfg quiet
	initrdefi /images/pxeboot/initrd.img
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;KS 启动项放在菜单第 1 位，而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set default=0&lt;/code&gt; 表示默认启动第 1 个菜单。&lt;/li&gt;
  &lt;li&gt;EFI grub.cfg 部分与 legacy BIOS 部分没有什么区别，主要是增加 ks.cfg 位置。&lt;/li&gt;
  &lt;li&gt;&apos;hd:LABEL=&apos; 同上。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这里虽然生成了 EFI 的 boot menu, 但是 ks.cfg 里没有创建对应的 ESP 分区，所以是实际无法以 EFI 启动安装。可以先手动用 UEFI 安装一次，再找修改，请参考 &lt;a href=&quot;https://forums.centos.org/viewtopic.php?t=71030&quot;&gt;UEFI Kickstart centos.org&lt;/a&gt; 和 &lt;a href=&quot;https://docs.openvz.org/openvz_installation_using_pxe_guide.webhelp/_kickstart_file_example_for_installing_on_efi_based_systems.html&quot;&gt;Kickstart Example for EFI-based system&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;7-generate-repodata&quot;&gt;7 Generate repodata&lt;/h3&gt;

&lt;p&gt;至此，各项准备工作完毕，开始执行关键命令。首先基于 comps.xml 生成 repodata 目录。repodata 目录包含 ISO 里所有文件的索引，comps.xml 等。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /mnt/iso

createrepo &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; douyu/c7-minimal-x86_64-comps.xml &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
ll repodata/

diff douyu/c7-minimal-x86_64-comps.xml repodata/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;c7-minimal-x86_64-comps.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;createrepo 会复制一份 comps.xml 进 repodata 目录，因此自定义的 comps.xml 不要放进 repodata.&lt;/p&gt;

&lt;h3 id=&quot;8-generate-new-iso-image&quot;&gt;8 Generate new ISO image&lt;/h3&gt;

&lt;p&gt;生成新 ISO 镜像。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /mnt/iso

genisoimage &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-joliet-long&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; isolinux/isolinux.bin &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; isolinux/boot.cat &lt;span class=&quot;nt&quot;&gt;-no-emul-boot&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-boot-load-size&lt;/span&gt; 4 &lt;span class=&quot;nt&quot;&gt;-boot-info-table&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-J&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cache-inodes&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eltorito-alt-boot&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; images/efiboot.img &lt;span class=&quot;nt&quot;&gt;-no-emul-boot&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;CentOS7&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; /home/jim/workspace/CentOS-7-dy.iso /mnt/iso/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;genisoimage 的参数顺序非常重要，不能随变改动。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Legacy BIOS 启动参数，对应 isolinux.cfg.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -R -J -cache-inodes -T&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;UEFI 启动参数，对应 EFI grub.cfg.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e images/efiboot.img -no-emul-boot&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Legacy BIOS 和 UEFI 被 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-eltorito-alt-boot&lt;/code&gt; 隔开。&lt;/p&gt;

    &lt;p&gt;二者皆附带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-no-emul-boot&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;最重要的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-V&lt;/code&gt; 参数后的标签必须与上面 isolinux.cfg 或 grub.cfg 里的 &apos;hd:LABEL=&apos; 相同。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;9-hybrid-iso&quot;&gt;9 Hybrid ISO&lt;/h3&gt;

&lt;p&gt;上面的制作的 ISO 只能以 CD 模式启动，Hybrid 模式 ISO 可同时用于制作 Usb stick 以硬盘模式启动。&lt;/p&gt;

&lt;p&gt;The isohybrid utility modifies a an ISO 9660 image generated with mkisofs, genisoimage, or compatible utilities, to be bootable as a CD-ROM or as a hard disk.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;isohybrid &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; /home/jim/workspace/CentOS-7.8-dy.iso
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;10-embed-md5-into-iso&quot;&gt;10 Embed MD5 into ISO&lt;/h3&gt;

&lt;p&gt;ISO 文件里有一个 section 为空，没有有效内容，因此正好用来填充该 ISO 其它有效内容的 MD5 值。implantisomd5 把 MD5 值注入 ISO 中，会修改 ISO 的内容。对应地，可以用 checkisomd5 命令检验 ISO 文件完整性。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;implantisomd5 /home/jim/workspace/CentOS-7.8-dy.iso

checkisomd5 /home/jim/workspace/CentOS-7.8-dy.iso
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;implantisomd5 只计算原始有效内容的 MD5 值，不是计算整个 ISO 的 MD5 值。同一 ISO 只能注入一次 MD5.&lt;/p&gt;

&lt;h2 id=&quot;install-new-iso-image&quot;&gt;Install New ISO Image&lt;/h2&gt;

&lt;p&gt;制作完毕 ISO 后开始安装。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;如果安装的初始界面出现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+[drm:vmw_host_log [vmwgfx]] *ERROR* Failed to send host log message&lt;/code&gt; 日志，是因为 VirtualBox 里 Display 的驱动设置问题，应从 VMSVGA 换成 VBoxVGA, 参考 https://unix.stackexchange.com/q/502540.&lt;/li&gt;
  &lt;li&gt;安装过程中，可以用 Alt+F1 进主界面，Alt+F2 进 Shell 界面。在 Shell 界面，可以查看 /tmp/{packaging,anaconda}.log 日志，也可以从 /run/install/repo 下找到外部文件。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;https://o-my-chenjian.com/2017/11/20/DIY-A-CentOS7-System/&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;todos&quot;&gt;Todos&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;https://superuser.com/a/359247 https://superuser.com/a/359247&lt;/li&gt;
  &lt;li&gt;openssl passwd /etc/shadow hash 原理。&lt;/li&gt;
  &lt;li&gt;ks.cfg 里如果包含 &apos;auth&apos;, 需要 AppStream 里的 &apos;authselect-compat&apos; package. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BZ#1640697&lt;/code&gt;. 查看 CentOS 8 的 Release Notes.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Terminal Shell Sed</title>
   <link href="/2019/11/30/terminal-shell-sed/"/>
   <updated>2019-11-30T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/11/30/terminal-shell-sed</id>
   <content type="html">&lt;p&gt;I was aimed to be an ICT expertise. However, still today, I don&apos;t quite get the basics of ICT origin. This post will help clarify the relations between Terminal, Shell and Sed.&lt;/p&gt;

&lt;p&gt;This is long story. Let&apos;s begin with Terminal. At the very beginning, the only interface with the giant (as big as a house) computer was &lt;em&gt;punched tape&lt;/em&gt; along with an human being operator. Afterwards, &lt;em&gt;terminal&lt;/em&gt; was created allowing individuals to interact with computer. Terminal is a &lt;em&gt;physical device&lt;/em&gt; like the following one:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/vt100.jpg&quot; alt=&quot;vt100&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Usually a computer allows multiple terminals online. Each terminal is connected to input devices (e.g. keyboard) and output devices (e.g. monitor screen). Hence, a terminal is more like a serial interface/port between the computer and its peripheral devices. Sometimes, we call the physical terminal as &lt;em&gt;console&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As time flies, standalone terminals were outdated and &lt;em&gt;virtual terminal&lt;/em&gt; emerged with smaller computer - Personal Compuer (PC). PC has only one screen and one keyboard embedded but allows switching (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-Alt-Fn&lt;/code&gt;) between multiple (6 by default, vt1 - vt6) virtual terminals. Each virtual terminal has a kernel device (/dev/tty1-6) that provides a means of input and output. It is a software terminal instead of a physical one. Most often, a virtual terminal has a &lt;em&gt;login manager&lt;/em&gt; in front before an account can interact with his default &lt;em&gt;login shell&lt;/em&gt; (i.e. POSIX Bash).&lt;/p&gt;

&lt;p&gt;Apart from virtual terminal, we have &lt;em&gt;terminal emulator&lt;/em&gt; when X window presents. Terminal emulator is similar to a virtual terminal but managed by an X server instead of directly by the kernel.&lt;/p&gt;

&lt;p&gt;We also have &lt;a href=&quot;https://unix.stackexchange.com/q/21147&quot;&gt;pseudo terminal&lt;/a&gt; (pts/xy) that is created and owned by a applications like &lt;em&gt;sshd&lt;/em&gt;, terminal emulator (e.g. &lt;em&gt;xterm&lt;/em&gt;) etc. A pseudo terminal is a device (e.g. file &lt;em&gt;/dev/pts/04&lt;/em&gt;), actually consisting of the master side and the slave side, though they appear to a single device name.&lt;/p&gt;

&lt;p&gt;When we &lt;em&gt;ssh&lt;/em&gt; to a remote server, we establish a secure TCP connection to the remote &lt;em&gt;sshd&lt;/em&gt; daemon. We run a remote application through SSH, by default, which is a Shell like &lt;em&gt;/bin/bash&lt;/em&gt; if we does not explicitly provide a command. The remote application needs a terminal for I/O, like STDIN/STDOUT/STDERR. So &lt;em&gt;sshd&lt;/em&gt; creates a pseudo terminal for the application (e.g. Bash). &lt;em&gt;sshd&lt;/em&gt; is associated with the master, while the remote application is associated with the slave. Here is simple data flow:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;|        local     |           Internet          |             remote            |
|                  |                             |                               |
| terminal --- ssh | --------------------------- | sshd - master -- slave - bash |
|                  |                             |                               |
|                  |                             |                               |
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After that, ssh/sshd transfer data between local terminal and remote pseudo terminal. Without the slave, how would the Bash process get its STDIN/STDOUT/STDERR? Similarly, terminal emulator (e.g. xterm) also creates pseudo terminal upon startup. The emulator connects to the master side while user processes connect to the slave side. The local terminal above probably is a pseudo terminal of terminal emulator nowadays.&lt;/p&gt;

&lt;p&gt;Sometimes you may hear of &quot;attach STDIN/STDOUT&quot; (like &lt;em&gt;docker attach&lt;/em&gt;). It actually means creating a pipe between local terminal (e.g. xterm) and the remote terminal (e.g. docker container).&lt;/p&gt;

&lt;p&gt;Now let&apos;s move on to Shell. Terminal is where input and output happen (like typing program names), but Shell is a &lt;em&gt;job&lt;/em&gt; manager (desktop manager does the same thing). Nowadays, OS (Linux, Unix etc.) schedules multiple processes concurrently, namely &lt;em&gt;mutli-tasking&lt;/em&gt; support. Shell is the multi-tasking interface with end users, capable of starting, stopping, suspending, resuming etc. jobs. Upon login, the default Shell is ready for interaction.&lt;/p&gt;

&lt;p&gt;With Shell, we can &lt;em&gt;suspend&lt;/em&gt; the current &lt;em&gt;job&lt;/em&gt; to background with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-Z&lt;/code&gt;. On the contratry, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fg&lt;/code&gt; put the first background job &lt;em&gt;foreground&lt;/em&gt; running again. Alternatively, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bg&lt;/code&gt; send the job running background instead of suspending it. To start a program running in background, we can append &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; to program like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;program-name &amp;amp;&lt;/code&gt;. Different Shells may have different syntax to manage jobs.&lt;/p&gt;

&lt;p&gt;Job is distinct from &lt;em&gt;process&lt;/em&gt;, but both of them relate to &lt;em&gt;program&lt;/em&gt;. A program is a static executable binary while a process is a running program. Job is only meaningful to Shell. Jobs refer to a &lt;em&gt;pipeline&lt;/em&gt; of processes that run interactively. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls | head&lt;/code&gt; launches two processes but the pipeline defines a single job. Therefore, a job of Shell corresponds to a &lt;em&gt;process group&lt;/em&gt; of OS. Shell assign each job a job ID apart from process PID assigned by the OS. To list existing jobs, just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jobs -l&lt;/code&gt; like:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;300 &amp;amp;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1] 21810
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;301 &amp;amp;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2] 21811
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;302 &amp;amp;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;3] 21812
user@tux ~/workspace/outsinre.github.com &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;jobs&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1]  21810 Running                 &lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;300 &amp;amp;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2]- 21811 Running                 &lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;301 &amp;amp;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;3]+ 21812 Running                 &lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;302 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Numbers in brackets are job IDs while numbers that follow job IDs are PID. More about job control, please refer to &lt;a href=&quot;http://www.faqs.org/docs/bashman/bashref_78.html&quot;&gt;Manual 7.1 Job Control Basics &lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;BTW, a &lt;em&gt;daemon&lt;/em&gt; does not belong to job as it _detach_es from Shell and gets out of Shell management. Process suspended or running in background belong to job. Putting a job background allows starting another job as the Shell is _release_d.&lt;/p&gt;

&lt;p&gt;Finally, we go to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt;. It is just a sample of the many programs managed by Shell. Nothing more required to clarify.&lt;/p&gt;

&lt;p&gt;Refer to &lt;a href=&quot;http://www.linusakesson.net/programming/tty/index.php&quot;&gt;the TTY demystified&lt;/a&gt; and &lt;a href=&quot;http://www.rkoucha.fr/tech_corner/pty_pdip.html&quot;&gt;Using pseudo-terminals (pty) to control interactive programs&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>sudo</title>
   <link href="/2019/04/13/sudo/"/>
   <updated>2019-04-13T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/04/13/sudo</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#sudo-front-end&quot; id=&quot;markdown-toc-sudo-front-end&quot;&gt;sudo Front End&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#policy-syntax&quot; id=&quot;markdown-toc-policy-syntax&quot;&gt;Policy Syntax&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configure-policy&quot; id=&quot;markdown-toc-configure-policy&quot;&gt;Configure Policy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#run-command&quot; id=&quot;markdown-toc-run-command&quot;&gt;Run Command&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#preserve-env&quot; id=&quot;markdown-toc-preserve-env&quot;&gt;Preserve Env&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;sudo-front-end&quot;&gt;sudo Front End&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;sudo&lt;/em&gt; allows a permitted user to execute a command as the superuser (by default) or another user (if provided), as specified by a &lt;em&gt;security policy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;sudo&lt;/em&gt; is just a front end and depends on a &lt;em&gt;plugin architecture&lt;/em&gt; to load different security policies. We can enable plugins in &lt;em&gt;/etc/sudo.conf&lt;/em&gt; as below. The default plugin is &lt;em&gt;sudoers&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@ip-172-31-34-111 ~]# &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; ^Plugin /etc/sudo.conf
Plugin sudoers_policy sudoers.so
Plugin sudoers_io sudoers.so
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once a plugin is enabled, we can configure its security policies. For example, security polices of plugin &lt;em&gt;sudoers&lt;/em&gt; is located in file &lt;em&gt;/etc/sudoers&lt;/em&gt; or &lt;em&gt;/etc/sudoers.d&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Third party developers can distribute their own plugins and security policies to work seamlessly with the &lt;em&gt;sudo&lt;/em&gt; front end. This post only talks about plugin &lt;em&gt;sudoers&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;List sudoers policy of a user.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# &lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ll&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-U&lt;/span&gt; &amp;lt;user&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;policy-syntax&quot;&gt;Policy Syntax&lt;/h1&gt;

&lt;p&gt;Check the &lt;a href=&quot;https://unix.stackexchange.com/a/18880&quot;&gt;SUDOERS FILE FORMAT&lt;/a&gt; section in the man page of &lt;em&gt;suoers(5)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;sudoers policy is prescribed with Extented Backus-Naur Form (EBNF). Do &lt;strong&gt;not&lt;/strong&gt; despair if you are unfamiliar with EBNF; it is fairly simple and take the chance to study it.&lt;/p&gt;

&lt;p&gt;An EBNF definition looks like the following.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;symbol ::= definition | alternate1 | alternate2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Special characters &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt; (optional, 0 or 1), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; (zero or more), and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; (one or more) mean the same thing as regex. Single quotes denote verbatim character string as opposed to a defined symbol (variable) name. The rest part of EBNF of &lt;em&gt;sudoer&lt;/em&gt; is left to yourself.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;sudoers&lt;/em&gt; file is composed of two types of entries: &lt;em&gt;alias&lt;/em&gt; and &lt;em&gt;user specification&lt;/em&gt;. The advantage of alias is to group multiple items together and assign a meaningful label. There exist four kinds of aliases, namely &apos;User_Alias&apos;, &apos;Runas_Alias&apos;, &apos;Host_Alias&apos; and &apos;Cmd_Alias&apos;. When there exist only few accounts and hostnames concerned, alias is optional.&lt;/p&gt;

&lt;p&gt;When a user is matched by multiple entries, they are applied in order but only the last match takes effect. Let&apos;s forget about EBNF and alias part (not the focus of this post). The following is a sample of user specification. It is divided into two groups by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt; separator. The left side defines the object while the right side defines the actions.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;USER HOSTNAME = (RUNAS_USER:RUNAS_GROUP) COMMANDS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;USER is the primary key, for which this entry is designated.&lt;/p&gt;

    &lt;p&gt;It can be a user name (e.g. &lt;em&gt;jim&lt;/em&gt;, user ID (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#1000&lt;/code&gt;), group name (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%wheel&lt;/code&gt;), group ID (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%#10&lt;/code&gt;) etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;HOSTNAME defines the location where this user specification takes effect. The &lt;em&gt;sudoers&lt;/em&gt; file can be shared among multiple systems.&lt;/p&gt;

    &lt;p&gt;This field can be hostname, IP address, network range etc. Attention please; the loopback interface, namely &lt;em&gt;locahost&lt;/em&gt; or &lt;em&gt;127.0.0.1&lt;/em&gt; will be ignored by &lt;em&gt;sudoers&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&apos;(RUNAS_USER:RUNAS_GROUP) COMMANDS&apos; refers to the combination of target user/group and target commands. They comprise an integrated component.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;&apos;(RUNAS_USER:RUNAS_GROUP)&apos; is an optional field. By default, it is assumed to be &apos;(root:root)&apos;. Usually, &apos;RUNAS_GROUP&apos; is optional and defaults to that of &apos;RUNAS_USER&apos;.&lt;/li&gt;
      &lt;li&gt;&apos;COMMANDS&apos; specifies the list of commands can be executed. By default, a user must authenticate himself by password before executing the command. We can prepend &apos;COMMANDS&apos; with &apos;NOPASSWD:&apos;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Multiple components are separated by comma. Special value &apos;ALL&apos; matches everything (e.g. any hostnames).&lt;/p&gt;

&lt;p&gt;Entry below means on &lt;em&gt;debain&lt;/em&gt; host, account &lt;em&gt;jim&lt;/em&gt; can run &lt;em&gt;/bin/ls&lt;/em&gt; as acount &lt;em&gt;operator&lt;/em&gt;; he can also run &lt;em&gt;/bin/kill&lt;/em&gt; and &lt;em&gt;/usr/bin/apg&lt;/em&gt; as &lt;em&gt;root&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim debian = (operator) NOPASSWD: /bin/ls, (root) /bin/kill, /usr/bin/apg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let us see a more aggressive config.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim ALL=(ALL:ALL) NOPASSWD: ALL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;configure-policy&quot;&gt;Configure Policy&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;To modify sudoers policy, please use &lt;em&gt;visudo&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Personally, I&apos;d like to put per-user policy file under directory &lt;em&gt;/etc/sudoers.d/&lt;/em&gt;. Usually, we name the file after the user account in question.&lt;/p&gt;

    &lt;p&gt;To make the directory loaded, add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#includedir&lt;/code&gt; directive in &lt;em&gt;/etc/sudoers&lt;/em&gt;. As per the man page, &lt;em&gt;sudo&lt;/em&gt; will read each policy file in &lt;em&gt;/etc/sudoers.d&lt;/em&gt;, &lt;a href=&quot;https://bugs.centos.org/view.php?id=5017&quot;&gt;skipping&lt;/a&gt; filenames that contain a dot &apos;.&apos; ro end with tilde &apos;~&apos;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is an example.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# visudo &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /etc/sudoers
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# visudo &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /etc/sudoers.d/user
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
gray	localhost	&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;jim&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; ALL
%wheel	ALL		&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;	&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; /bin/iptables
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once finished editting, use the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-c&lt;/code&gt; to verify syntax.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# visudo &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /etc/sudoers
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# visudo &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /etc/sudoers.d/user
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then check the result:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# &lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ll&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-U&lt;/span&gt; &amp;lt;user&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;run-command&quot;&gt;Run Command&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# run as root&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;user@host ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &amp;lt;&lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# run as specific user&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;userhost ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; &amp;lt;target-user&amp;gt; &amp;lt;&lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the command to ran is to edit a protected file, &lt;a href=&quot;https://superuser.com/q/785187&quot;&gt;sudoedit&lt;/a&gt; is preferred than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo vim&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;preserve-env&quot;&gt;Preserve Env&lt;/h2&gt;

&lt;p&gt;Sometimes it is useful to bring current Envs to target user (e.g. &lt;em&gt;root&lt;/em&gt;) and commands, so that we don&apos;t bother to set again. There are multiple methods to achieve this.&lt;/p&gt;

&lt;p&gt;Set an Env in current user.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-34-111 ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;MY_VAR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;123

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-34-111 ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$MY_VAR&lt;/span&gt;
123

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-34-111 ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printenv&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;MY_VAR
&lt;span class=&quot;nv&quot;&gt;MY_VAR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;123
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Three methods as below.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Globally set by plugin &lt;em&gt;sudoers&lt;/em&gt;. By default, &lt;em&gt;/etc/sudoers&lt;/em&gt; enables option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env_reset&lt;/code&gt; to reset Envs so that commands are ran in a new, minimal environment, including TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME, etc.&lt;/p&gt;

    &lt;p&gt;We can add to the default list new Envs by option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env_keep&lt;/code&gt; and/or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env_check&lt;/code&gt; like below. Envs in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env_keep&lt;/code&gt; will be preserved while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env_check&lt;/code&gt; will remove Envs that is &lt;em&gt;unsafe&lt;/em&gt;. Unsafe Envs refer to those Envs that contain character &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Defaults    env_reset
Defaults    env_keep =  &quot;COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS&quot;
Defaults    env_keep += &quot;MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE&quot;
Defaults    env_keep += &quot;LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES&quot;
Defaults    env_keep += &quot;LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE&quot;
Defaults    env_keep += &quot;LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY&quot;
   
Defaults    env_keep += &quot;MY_VAR1 MY_VAR2&quot;

Defaults    env_check = &quot;MY_VAR1 MY_VAR2&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Alternatively, we can even prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env_reset&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; to disable the default behaviour, so that all Envs are preserved. But this is not recommended.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Defaults !env_reset
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Setting by security policies is globally available and applies to all scenarios.&lt;/p&gt;

    &lt;p&gt;Refer to &apos;Command environment&apos; section of &lt;em&gt;sudoers&lt;/em&gt; man page.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Set &lt;em&gt;sudo&lt;/em&gt; option &lt;a href=&quot;https://stackoverflow.com/a/8633575/2336707&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-E, --preserve-env[=list]&lt;/code&gt;&lt;/a&gt; to &lt;em&gt;sudo&lt;/em&gt;. We can restrict Envs by opt-arg &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=list&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;This method is convenient, especially for user-defined Envs.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Set directly on CLI.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-34-111 ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;MY_VAR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$MY_VAR&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printenv&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;MY_VAR
&lt;span class=&quot;nv&quot;&gt;MY_VAR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;123
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The &lt;em&gt;env&lt;/em&gt; is optional but suggested to be present when preserving default Envs like &apos;PATH&apos;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-34-111 ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo printenv&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; ^PATH
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/sbin:/bin:/usr/sbin:/usr/bin

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;ec2-user@ip-172-31-34-111 ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo env&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;PATH=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;printenv&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; ^PATH
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/ec2-user/.local/bin:/home/ec2-user/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This method is stupid but powerful.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before closing this section, please be cautious that bringing current Envs to target user/command is &lt;a href=&quot;https://superuser.com/q/232231/221946&quot;&gt;dangerous&lt;/a&gt;. For example, sudo by default enables option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secure_path&lt;/code&gt; to &lt;a href=&quot;https://unix.stackexchange.com/q/83191/74407&quot;&gt;restrict the PATH&lt;/a&gt; as below, so that only secure PATH is included. That is the reason we need to add &lt;em&gt;env&lt;/em&gt; when preserving PATH in method 3 above.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@ip-172-31-34-111 ~]# &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;secure_path /etc/sudoers
Defaults    secure_path &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; /sbin:/bin:/usr/sbin:/usr/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of course, if you&apos;d like, updating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;secure_path&lt;/code&gt; policy is also fine.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ZooKeeper and Kafka</title>
   <link href="/2019/04/11/zookeeper-kafka/"/>
   <updated>2019-04-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/04/11/zookeeper-kafka</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#zookeeper-abcs&quot; id=&quot;markdown-toc-zookeeper-abcs&quot;&gt;ZooKeeper ABCs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#quorum&quot; id=&quot;markdown-toc-quorum&quot;&gt;Quorum&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#kafka-abcs&quot; id=&quot;markdown-toc-kafka-abcs&quot;&gt;Kafka ABCs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#deployment&quot; id=&quot;markdown-toc-deployment&quot;&gt;Deployment&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#references&quot; id=&quot;markdown-toc-references&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#prerequisites&quot; id=&quot;markdown-toc-prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#docker&quot; id=&quot;markdown-toc-docker&quot;&gt;Docker&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#account---logger&quot; id=&quot;markdown-toc-account---logger&quot;&gt;Account - logger&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#latest-centos-7&quot; id=&quot;markdown-toc-latest-centos-7&quot;&gt;Latest CentOS 7&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#dockerfile&quot; id=&quot;markdown-toc-dockerfile&quot;&gt;Dockerfile&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#build-image&quot; id=&quot;markdown-toc-build-image&quot;&gt;Build Image&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#create-container&quot; id=&quot;markdown-toc-create-container&quot;&gt;Create Container&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#container-setup&quot; id=&quot;markdown-toc-container-setup&quot;&gt;Container Setup&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#java-8&quot; id=&quot;markdown-toc-java-8&quot;&gt;Java 8&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#zookeeper-replicated-mode&quot; id=&quot;markdown-toc-zookeeper-replicated-mode&quot;&gt;ZooKeeper Replicated Mode&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#zookeeper-startup&quot; id=&quot;markdown-toc-zookeeper-startup&quot;&gt;ZooKeeper Startup&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#zookeeper-logging&quot; id=&quot;markdown-toc-zookeeper-logging&quot;&gt;ZooKeeper Logging&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#zookeeper-status&quot; id=&quot;markdown-toc-zookeeper-status&quot;&gt;ZooKeeper Status&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#zookeeper-storage&quot; id=&quot;markdown-toc-zookeeper-storage&quot;&gt;ZooKeeper Storage&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#stop-zookeeper&quot; id=&quot;markdown-toc-stop-zookeeper&quot;&gt;Stop ZooKeeper&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#zookeeper-systemd-unit&quot; id=&quot;markdown-toc-zookeeper-systemd-unit&quot;&gt;ZooKeeper Systemd Unit&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#zookeeper-advanced-tips&quot; id=&quot;markdown-toc-zookeeper-advanced-tips&quot;&gt;Zookeeper Advanced Tips&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#dynamic-reconfiguration&quot; id=&quot;markdown-toc-dynamic-reconfiguration&quot;&gt;Dynamic Reconfiguration&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#observer-server&quot; id=&quot;markdown-toc-observer-server&quot;&gt;Observer Server&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#kafka&quot; id=&quot;markdown-toc-kafka&quot;&gt;Kafka&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#kafka-installation&quot; id=&quot;markdown-toc-kafka-installation&quot;&gt;Kafka Installation&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#kafka-configuration&quot; id=&quot;markdown-toc-kafka-configuration&quot;&gt;Kafka Configuration&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-kafka&quot; id=&quot;markdown-toc-start-kafka&quot;&gt;Start Kafka&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#kafka-status&quot; id=&quot;markdown-toc-kafka-status&quot;&gt;Kafka Status&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#stop-kafka&quot; id=&quot;markdown-toc-stop-kafka&quot;&gt;Stop Kafka&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#topic-creation&quot; id=&quot;markdown-toc-topic-creation&quot;&gt;Topic Creation&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#console-producer-and-consumer&quot; id=&quot;markdown-toc-console-producer-and-consumer&quot;&gt;Console Producer and Consumer&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#consumer-group&quot; id=&quot;markdown-toc-consumer-group&quot;&gt;Consumer Group&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#kafka-security&quot; id=&quot;markdown-toc-kafka-security&quot;&gt;Kafka Security&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#dynamic-update-mode&quot; id=&quot;markdown-toc-dynamic-update-mode&quot;&gt;Dynamic Update Mode&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;zookeeper-abcs&quot;&gt;&lt;a href=&quot;https://zookeeper.apache.org/doc/current/zookeeperOver.html&quot;&gt;ZooKeeper ABCs&lt;/a&gt;&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;Kafka replies on and is the client of ZooKeeper.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/zkservice.jpg&quot; alt=&quot;zkservice&quot; /&gt;&lt;/p&gt;

&lt;p&gt;ZooKeeper is a Distributed Coordination Service for Distributed Applications (i.e. Kafka), relieving them from coordination but focusing on high-level synchronization, configuration maintenance, and groups and naming.&lt;/p&gt;

&lt;p&gt;ZooKeeper defines a hierarchical namespace similar to the structure and a Linux filesystem like the figure below. Each node in the tree is named as a path starting with a forward slash &apos;/&apos; (the root node). In ZooKeeper parlance, a tree node is called &lt;em&gt;znode&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/zknamespace.jpg&quot; alt=&quot;zknamespace&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As ZooKeeper is designed to coordinate data (like metadata, configuration, location etc.), so the data stored in each znode is usually small in the byte to kilobyte range. ZooKeeper keeps the data in memory for high throughput and low latency. Meanwhile, snapshots of the in-memory data is kept in a persistent storage (disk) along with transaction logs. Transaction logs refer to logs of clients&apos; read and write operations.&lt;/p&gt;

&lt;p&gt;Like the applications it coordinates, ZooKeeper itself is also distributed and replicated across a cluster of hosts - ZooKeeper &lt;em&gt;ensemble&lt;/em&gt;. The in-memory data and persistent data are replicated among the ZooKeeper servers.&lt;/p&gt;

&lt;p&gt;The servers that make up the ZooKeeper ensemble must all know about each other (by configuration file). ZooKeeper performs &lt;em&gt;heartbeat&lt;/em&gt;s test (a tiny packet) periodically to check connection and availability of servers.&lt;/p&gt;

&lt;p&gt;At any give moment, a client (a coordinated application) connects (TCP connection) to a single ZooKeeper server, and switch to another one if the current TCP connection breaks. Read requests are served locally while requests to change the state of data (write requests) are all forwarded to a particular server called &lt;em&gt;leader&lt;/em&gt;. The rest servers are called &lt;em&gt;follower&lt;/em&gt;s (similar to partitions leader and followers of Kafka). Followers replicate write results from the leader to keep synchronized.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Write synchronization is the core of ZooKeeper.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The underlying implementation takes care of replacing the leader upon failure and syncing followers with the leader.&lt;/p&gt;

&lt;h1 id=&quot;quorum&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Quorum&quot;&gt;Quorum&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;According to Wikipedia, a &lt;em&gt;quorum&lt;/em&gt; is the &lt;em&gt;minimum number&lt;/em&gt; of members of a deliberative assembly necessary to conduct the business of that group. A quorum requirement is protection against totally unrepresentative action in the name of the body by an &lt;em&gt;unduly&lt;/em&gt; small number of persons. A quorum is often more than half of the total number.&lt;/p&gt;

&lt;p&gt;ZooKeeper is functional only when a quorum of the servers are available. Recall that all writes requests are forwarded to the leader in ZooKeeper. Upon successive write, the result is synced to followers. If less than a quorum of the servers are synched on the write, ZooKeeper was nonfunctional as &apos;write synchronization is the core&apos;.&lt;/p&gt;

&lt;p&gt;Take 4 ZooKeeper servers for example, a quorum is 3 (&amp;gt; 4/2) which allows 1 server failure and writes should be synced among 3 servers. If there are only 3 servers, the quorum is 2 (&amp;gt; 3/2) which is able to allow 1 server failure as well. So the additional 4th server does not bring in any improvement in terms of stability. However, it benefits load balancing. But what if the number is increased to 5? This requires 3 (&amp;gt; 5/2) servers to form a quorum, the same as a 4-server ZooKeeper. However, the system allows 2 server failure and is more fault-tolerant. Usually, either 3 or 5, not 4 - choose an &lt;strong&gt;odd&lt;/strong&gt; number, namely 1, 3, 5, etc.&lt;/p&gt;

&lt;p&gt;ZooKeeper elects the leader from at least of a quorum of the servers. Therefore, proper choice of the number of servers is essential for deployment. If there is only 1 server, it forms the &lt;em&gt;standalone mode&lt;/em&gt;, otherwise, it is &lt;em&gt;replicated mode&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A basic rule:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;At least a quorum of ZooKeeper servers are online (active);&lt;/li&gt;
  &lt;li&gt;At least a quorum of active ZooKeeper servers are synched on a &apos;write&apos; operation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Read more about quorum at &lt;a href=&quot;http://www.corejavaguru.com/blog/bigdata/why-zookeeper-on-odd-number-nodes.php&quot;&gt;why-zookeeper-on-odd-number-nodes?&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;kafka-abcs&quot;&gt;&lt;a href=&quot;https://kafka.apache.org/intro&quot;&gt;Kafka ABCs&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/assets/kafka-apis.png&quot; alt=&quot;Kafka Arch&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Kafka is a &lt;em&gt;distributed streaming&lt;/em&gt; platform.
    &lt;ol&gt;
      &lt;li&gt;Streaming: real-time messaging pipeline similar to Logstash and different from Elasticsearch that is a static storage.&lt;/li&gt;
      &lt;li&gt;Distributed: cluster with fault-tolerance and load balancing.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Kafka receives data from &lt;em&gt;producer&lt;/em&gt;s while streaming it to &lt;em&gt;consumer&lt;/em&gt;s (also called &lt;em&gt;subscriber&lt;/em&gt;s). In this post, words &lt;em&gt;read&lt;/em&gt; and &lt;em&gt;consume&lt;/em&gt; are used interchangeably; &lt;em&gt;write&lt;/em&gt; and &lt;em&gt;produce&lt;/em&gt; are used interchangeably. However, read and write emphasize internal actions while produce and consume emphasize interactions with external applications.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Kafka and Logstash are both message pipeline.&lt;/p&gt;

    &lt;p&gt;However, Kafka is more powerful. Basically, Kafka is a cluster while Logstash runs in standalone mode.&lt;/p&gt;

    &lt;p&gt;They can co-operate: each Logstash instance connects to a Kafka server (also called &lt;em&gt;broker&lt;/em&gt;) in the cluster. Logstash instances are not aware of each other.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Kafka uses the term &lt;em&gt;record&lt;/em&gt; or &lt;em&gt;message&lt;/em&gt; while Elastic Stack and Flume use &lt;em&gt;event&lt;/em&gt;, namely the data.&lt;/p&gt;

    &lt;p&gt;Each record comprises &lt;em&gt;timestamp&lt;/em&gt;, &lt;em&gt;metadata&lt;/em&gt; other key-value pairs.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{&quot;@timestamp&quot;:&quot;2019-04-17T09:45:22.361Z&quot;,&quot;@metadata&quot;:{&quot;beat&quot;:&quot;filebeat&quot;,&quot;type&quot;:&quot;_doc&quot;,&quot;version&quot;:&quot;7.0.0&quot;,&quot;topic&quot;:&quot;var-logs&quot;},&quot;message&quot;:&quot;127.0.0.1 - - [17/Apr/2019:09:45:19 +0000] \&quot;GET /index.html HTTP/1.1\&quot; 200 3700 \&quot;-\&quot; \&quot;curl/7.29.0\&quot; \&quot;-\&quot;&quot;,&quot;log&quot;:{&quot;offset&quot;:505,&quot;file&quot;:{&quot;path&quot;:&quot;/var/log/nginx/access.log&quot;}},&quot;input&quot;:{&quot;type&quot;:&quot;log&quot;},&quot;ecs&quot;:{&quot;version&quot;:&quot;1.0.0&quot;},&quot;host&quot;:{&quot;name&quot;:&quot;76595710480d&quot;,&quot;architecture&quot;:&quot;x86_64&quot;,&quot;os&quot;:{&quot;platform&quot;:&quot;centos&quot;,&quot;version&quot;:&quot;7 (Core)&quot;,&quot;family&quot;:&quot;redhat&quot;,&quot;name&quot;:&quot;CentOS Linux&quot;,&quot;kernel&quot;:&quot;3.10.0-693.el7.x86_64&quot;,&quot;codename&quot;:&quot;Core&quot;},&quot;containerized&quot;:true,&quot;hostname&quot;:&quot;76595710480d&quot;},&quot;agent&quot;:{&quot;ephemeral_id&quot;:&quot;8909f3d3-8037-4288-bf12-7f22e821181b&quot;,&quot;hostname&quot;:&quot;76595710480d&quot;,&quot;id&quot;:&quot;0c54a8df-1b11-421a-b91b-98a18b4d1ff0&quot;,&quot;version&quot;:&quot;7.0.0&quot;,&quot;type&quot;:&quot;filebeat&quot;},&quot;cloud&quot;:{&quot;instance&quot;:{&quot;id&quot;:&quot;i-00000472&quot;,&quot;name&quot;:&quot;apple-dev.novalocal&quot;},&quot;machine&quot;:{&quot;type&quot;:&quot;8C16G100G&quot;},&quot;availability_zone&quot;:&quot;nova&quot;,&quot;provider&quot;:&quot;openstack&quot;}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Topic, Partition and Commit Log&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/kafka-partition.png&quot; alt=&quot;Kafka Partition&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;Records are classified into &lt;em&gt;topic&lt;/em&gt;s: categories of records. We can regard the topic as a label assigned to a group of relevant records (i.e. Nginx logs). Records of a particular topic are stored in one or more (determined at topic creation) &lt;em&gt;partition&lt;/em&gt;s with individual records replicated in one or more partitions (determined at topic creation).&lt;/p&gt;

    &lt;p&gt;A partition is an &lt;em&gt;ordered&lt;/em&gt; and &lt;em&gt;immutable&lt;/em&gt; sequence of records with new records continuously appended to, similar to an array disallowing random write.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Write in order while read in a free style.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Multiple partitions act as a parallelism to speed up producing and consuming. Additionally, the capacity of a partition may be limited by the Kafka server hold it. So multiple partitions accomplish storage scalability. Typically, partititons reside on dedicated high speed I/O devices like SSD.&lt;/p&gt;

    &lt;p&gt;Records in partitions form a structured &lt;em&gt;commit log&lt;/em&gt;. In the context of Kafka, &lt;a href=&quot;https://stackoverflow.com/q/40369238&quot;&gt;&quot;log&quot; refers to topic data&lt;/a&gt;, &lt;strong&gt;NOT&lt;/strong&gt; the log of Kafka itself. The relevant configuration directive is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log.dir&lt;/code&gt;. In this post, we call them &lt;em&gt;commit log&lt;/em&gt; and &lt;em&gt;broker log&lt;/em&gt; separately.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Offset&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/kafka-read-write.png&quot; alt=&quot;Kafka Read and Write&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;A record is uniquely identified by the &lt;em&gt;index&lt;/em&gt; within a partition, which is called &lt;em&gt;offset&lt;/em&gt; - the only metadata retained by each consumer. For sequential consumption, the offset is reduced one by one. Consumers are independent of each other. We can use command line &lt;em&gt;tail -F&lt;/em&gt; to examine the topic records without interfering in what is and what can be consumed.&lt;/p&gt;

    &lt;p&gt;Records sent by a particular producer to a particular topic partition are appended in the order they are sent. However Kafka only guarantees such order on a per-partition base. The order of records among consumers, producers and/or partitions are not forseeable. If that is the desired outcome, then configure only one partition for a topic and only one consumer instance per &lt;em&gt;consumer group&lt;/em&gt; (discussed below).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Persistent Storage&lt;/p&gt;

    &lt;p&gt;Kafka can be configured to hold records for a retention period of time. During that period, a record is available for consumption, after which it is discarded to free up space.&lt;/p&gt;

    &lt;p&gt;Consumption does not mean to eat up records but just read. Whether to get rid of a record depends on the retention configuration. The read/write performance is &lt;em&gt;constant&lt;/em&gt; with respect to storage size so storing data for a long time is not a problem.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Distribution&lt;/p&gt;

    &lt;p&gt;Each partition is replicated across a configurable number of Kafka brokers - the &lt;em&gt;replication factor&lt;/em&gt; for fault tolerance. Of the replicated brokers, one is the &lt;em&gt;leader&lt;/em&gt; and the rest are &lt;em&gt;follower&lt;/em&gt;s (recall the leader and follower of Zookeeper). At any given moment, the leader broker handles both readding and writing operation (different from that of Zookeeper) while the rest brokers only replicate the leader.&lt;/p&gt;

    &lt;p&gt;A leader has to maintain a list of followers that are &lt;em&gt;in-sync replicas&lt;/em&gt; (ISR). An ISR means the follower has fully caught up with the leader, namely synced in time. If a leader fails, one of the ISR followers becomes the new leader.&lt;/p&gt;

    &lt;p&gt;From the perspective of a Kafka broker, it holds a share of existing partitions and acts as a leader for some of its partitions and a follower for others.&lt;/p&gt;

    &lt;p&gt;Therefore, load is well balanced within the cluster.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Producer&lt;/p&gt;

    &lt;p&gt;A producer publish data to the records of its choice and decide the partition to which a record is assigned to. The assignment can be done in a round robin fashion to load balance or based on key values.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Consumer Group&lt;/p&gt;

    &lt;p&gt;A topic can have zero or more consumers which are also assigned to labels, forming &lt;em&gt;consumer group&lt;/em&gt;s (also called &lt;em&gt;subscriber group&lt;/em&gt;). That is to say, all consumers subscribing to a topic are divided into groups. That makes a sense as there may exist multiple entities interested in the same topic, with each entity forms a subscriber group. &lt;em&gt;Consumer instance&lt;/em&gt;s within a group can be separate threads, processes or machines.&lt;/p&gt;

    &lt;p&gt;Partitions of a topic are effectively load-balanced over the consumer instances of a subscribing group, in a granularity of partitions. Each instance &lt;em&gt;exclusively&lt;/em&gt; consumes zero or more of the partitions at any given time. If there are more instances than partitions, then some of them may be in idle state, consuming nothing. In the other way around, each partition is &lt;em&gt;broadcasted&lt;/em&gt; in a granularity of subscribing groups.&lt;/p&gt;

    &lt;p&gt;In the figure below, there are 4 partitions (P0 - P3) belonging to a particular topic (replication is left out for simplifition). From the figure, each partition is broadcasted to both group A and group B. Within either group, partitions are exclusively distributed.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/kafka-consumer-groups.png&quot; alt=&quot;Subscribing Groups&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;Subscribing groups achieve multi-subscriber support (with the help of persistent storage), namely scalability. Within each group, Kafaka achives parallelism and load balance. The points are:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Broadcast among groups.&lt;/li&gt;
      &lt;li&gt;Exclusive distribution among consumer instances of a group.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;A consumer group can be esteemed as a &lt;em&gt;logical subscriber&lt;/em&gt;. In terms of scalability, load balance, and fault tolerance:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Groups can also leave and join the system.&lt;/li&gt;
      &lt;li&gt;Instances can dynamically join (get a share from other instances) and/or leave (i.e. die) a group (its partitions are transferred to others).&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;By the way, consumer group has a unique identifier that is &lt;a href=&quot;https://stackoverflow.com/q/43118671&quot;&gt;created by Java consumer API&lt;/a&gt;, &lt;em&gt;not&lt;/em&gt; by ZooKeeper or Kafka producer.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Early versions of Kafka depends on &lt;em&gt;external&lt;/em&gt; Zookeeper. Recent Kafka has built Zookeeper into release packages. More aggressively, Kafka (&amp;gt;= 2.8.0) can &lt;a href=&quot;https://kafka.apache.org/quickstart&quot;&gt;run without Zookeeper&lt;/a&gt;, with self-managed quorum (e.g. Kafka Raft).&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;deployment&quot;&gt;&lt;a href=&quot;https://progressive-code.com/post/17/Setup-a-Kafka-cluster-with-3-nodes-on-CentOS-7&quot;&gt;Deployment&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;This post will deploy a ZooKeeper cluster and Kafka cluster with 3 Docker containers for testing purpose. All the 3 containers reside on the same physical host.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Container&lt;/th&gt;
      &lt;th&gt;IP&lt;/th&gt;
      &lt;th&gt;Servers&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;logger1&lt;/td&gt;
      &lt;td&gt;172.17.0.2&lt;/td&gt;
      &lt;td&gt;ZooKeeper 1, Kafka 1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;logger2&lt;/td&gt;
      &lt;td&gt;172.17.0.3&lt;/td&gt;
      &lt;td&gt;ZooKeeper 2, Kafka 2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;logger3&lt;/td&gt;
      &lt;td&gt;172.17.0.4&lt;/td&gt;
      &lt;td&gt;ZooKeeper 3, Kafka 3&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://progressive-code.com/post/17/Setup-a-Kafka-cluster-with-3-nodes-on-CentOS-7&quot;&gt;Setup a Kafka cluster with 3 nodes on CentOS 7&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.51cto.com/qiangsh/2112675&quot;&gt;51cto&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://beckjin.com/2018/11/18/kafka-cluster/&quot;&gt;beckjin&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Docker CentOS 7;&lt;/li&gt;
  &lt;li&gt;Java 8;&lt;/li&gt;
  &lt;li&gt;ZooKeeper MUST be ran before Kafka.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;docker&quot;&gt;Docker&lt;/h2&gt;

&lt;h3 id=&quot;account---logger&quot;&gt;Account - logger&lt;/h3&gt;

&lt;p&gt;Create an account &apos;logger&apos; in both the host and containers. The name &apos;logger&apos; is chosen to represent ZooKeeper and Kafka respectively. Its home directery is the main place to share critical configuration files. This is optional as we can create the new account within containers directly. It is listed just as a practice.&lt;/p&gt;

&lt;p&gt;First create the account in the physical host. We&apos;d better keep the user ID and group ID consistent in case of permission conflicts. In this post, we set both IDs to 555. In Linux practice, &lt;em&gt;manually&lt;/em&gt; created user ID and group ID are suggested to be &lt;em&gt;equal to or larger than 1000&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# groupadd -g 555 logger&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# useradd -ms /bin/bash -u 555 -g logger logger&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# passwd logger&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# id logger&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# su - logger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create a shared directory between the host and containers:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /var/opt/logger&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# chown -R logger:logger /var/opt/logger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;latest-centos-7&quot;&gt;Latest CentOS 7&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# docker search centos&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# docker pull centos&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# docker image ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;dockerfile&quot;&gt;Dockerfile&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;In the Dockerfile, we pass a default password for &apos;logger&apos;, which should be changed after &lt;em&gt;docker attach&lt;/em&gt; or &lt;em&gt;docker exec&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Enable EPEL and IUS, and install a few tools (&lt;a href=&quot;http://xmodulo.com/linux-tcpip-networking-net-tools-iproute2.html&quot;&gt;iproute2 vs net-tools&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;FROM centos:latest
RUN groupadd -g 555 logger ; useradd -ms /bin/bash -u 555 -g logger logger ; echo &quot;logger:12345678&quot; | chpasswd
RUN yum install -y epel-release https://centos7.iuscommunity.org/ius-release.rpm
RUN yum install -y sudo iproute most nmap-ncat java-1.8.0-openjdk
CMD [&quot;/bin/bash&quot;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remember to change password upon login.&lt;/p&gt;

&lt;h3 id=&quot;build-image&quot;&gt;Build Image&lt;/h3&gt;

&lt;p&gt;The Dockerfile is read from STDIN (dash).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker build &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; centos-7.6:logger - &amp;lt; Dockerfile
logger@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker image &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;create-container&quot;&gt;Create Container&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Create an alias in &lt;em&gt;/etc/hosts&lt;/em&gt; for the host IP by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--add-host&lt;/code&gt;, making connections to the host easier.&lt;/li&gt;
  &lt;li&gt;Use the default &apos;bridge&apos; networking mode; run as the default &apos;root&apos;.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@tux ~ &lt;span class=&quot;c&quot;&gt;# HOSTIP=&quot;$( awk -F $&apos;/|[[:space:]]+&apos; &apos;{print $4}&apos; &amp;lt; &amp;lt;(ip -4 -o address show scope global dev eth0) )&quot;&lt;/span&gt;

logger@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; logger1 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;,source&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/opt/logger,target&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/opt/logger &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; /var/opt/logger &lt;span class=&quot;nt&quot;&gt;--net&lt;/span&gt; bridge &lt;span class=&quot;nt&quot;&gt;--add-host&lt;/span&gt; host-eth0:&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOSTIP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; root:root centos-7.6:logger bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;container-setup&quot;&gt;Container Setup&lt;/h3&gt;

&lt;p&gt;By default, containers&apos;s hostname is set to the value of their IDs. So &apos;localhost&apos; in &lt;em&gt;sudoers&lt;/em&gt; does not work as expected.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# docker container ls&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# docker attach logger1&lt;/span&gt;
root@container ~ &lt;span class=&quot;c&quot;&gt;# passwd logger&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &amp;lt;new password&amp;gt;&lt;/span&gt;

root@container ~ &lt;span class=&quot;c&quot;&gt;# visudo [-c] -f /etc/sudoers.d/logger&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# logger $(hostname) = (root) ALL&lt;/span&gt;

root@container ~ &lt;span class=&quot;c&quot;&gt;# visudo -cf /etc/sudoers.d/logger&lt;/span&gt;
root@container ~ &lt;span class=&quot;c&quot;&gt;# sudo -ll -U logger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Switch to the new account:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@container ~ &lt;span class=&quot;c&quot;&gt;# su - logger&lt;/span&gt;

logger@container ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;PS1=&quot;[\u@\h-logger1 \W]\$ &quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Insert &lt;em&gt;logger1&lt;/em&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PS1&lt;/code&gt;, making it easier to differentiate containers on shell prompt.&lt;/p&gt;

&lt;h2 id=&quot;java-8&quot;&gt;Java 8&lt;/h2&gt;

&lt;p&gt;Install JRE:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;yum repolist
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;java &lt;span class=&quot;nt&quot;&gt;-version&lt;/span&gt;

logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;yum search java-1.8.0-openjdk
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;java-1.8.0-openjdk.x86_64
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;java &lt;span class=&quot;nt&quot;&gt;-version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;System property value can be configured dynamically on command line by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java -Dproperty=value&lt;/code&gt;. &lt;em&gt;property&lt;/em&gt; is a Java variable while &lt;em&gt;value&lt;/em&gt; overrides the counterpart set in configuration files. If &lt;em&gt;value&lt;/em&gt; is a string with blanks, then quote it.&lt;/p&gt;

&lt;h1 id=&quot;zookeeper-replicated-mode&quot;&gt;&lt;a href=&quot;http://zookeeper.apache.org/doc/current/zookeeperStarted.html&quot;&gt;ZooKeeper Replicated Mode&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;The installation is quite easy: just &lt;a href=&quot;http://zookeeper.apache.org/releases.html&quot;&gt;download&lt;/a&gt; and extract the tarball. Stable versions are recommended! As of writing this post, stable 3.4.14 is available.&lt;/p&gt;

&lt;p&gt;Install ZooKeeper to &lt;em&gt;/opt&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; /var/opt/logger https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/stable/zookeeper-3.4.14.tar.gz
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xzpvf&lt;/span&gt; /var/opt/logger/zookeeper-3.4.14.tar.gz &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; /opt/
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sv&lt;/span&gt; zookeeper-3.4.14 zookeeper
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; logger:logger zookeeper/
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;zookeeper/conf/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, we focus on the configuration. A sample configuration file is located at &lt;em&gt;zookeeper/conf/zoo_sample.cfg&lt;/em&gt;. We are interested in the following &lt;a href=&quot;https://zookeeper.apache.org/doc/r3.4.14/zookeeperAdmin.html#sc_configuration&quot;&gt;directives&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;tickTime: basic unit in milliseconds; heartbeats interval - the &lt;em&gt;tick&lt;/em&gt;. The minimum timeout value will be &lt;em&gt;twice&lt;/em&gt; the &apos;tickTime&apos; and the maximum timeout value is 10 times.&lt;/li&gt;
  &lt;li&gt;initLimit: timeout for servers in quorum to connect to the leader.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;syncLimit: timeout between sending a update request to and receiving acknowledgement from a leader.&lt;/p&gt;

    &lt;p&gt;The two directives are not required in standalone mode.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;dataDir: persistent storage for both snapshots of in-memory data and trasaction logs.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;dataLogDir: a dedicated directive that defines a different location to store transactions logs.&lt;/p&gt;

    &lt;p&gt;A separate physical storage device for transaction logs can significantly improve performance of ZooKeeper.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;clientPort: the port to listen for client (Kafka brokers in this case) connections. By default, it is 2181.&lt;/p&gt;

    &lt;p&gt;clientPortAddress is the address to listen for client connections. By default, it is &apos;0.0.0.0&apos;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;autopurge.snapRetainCount: when doing storage cleanup, only retain the most recent version. No less than 3!&lt;/li&gt;
  &lt;li&gt;autopurge.purgeInterval: cleanup interval in hour unit.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;server.X=hostname:port1:port2:&lt;/p&gt;

    &lt;p&gt;Specify ZooKeeper servers where X is an integer between 1 and 255, being the &lt;em&gt;unique identifier&lt;/em&gt; within the ensemble. The first port number &lt;em&gt;port1&lt;/em&gt; (default to 2888) is for followers to connect to the leader; the next &lt;em&gt;port2&lt;/em&gt; (default to 3888) is for leader selection.&lt;/p&gt;

    &lt;p&gt;Standalone mode does not require the &apos;server.X&apos; directive, but can also specify a single line like &apos;server.1=localhost:2888:3888&apos;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If multiple servers run on a single host, choose separate ports, directroies etc. The name &lt;em&gt;tick&lt;/em&gt; is the basic unit in measuring timeout. When setting up ZooKeeper in standalone mode (1 server only), &apos;initLimit&apos; and &apos;syncLimit&apos; are ignored as there is no synchronization requirement. Standalone mode is handy when testing development.&lt;/p&gt;

&lt;p&gt;The configuration file uses &lt;a href=&quot;https://en.wikipedia.org/wiki/.properties&quot;&gt;.properties&lt;/a&gt; format, and can be any name, but often we use &lt;em&gt;conf/zoo.cfg&lt;/em&gt; (check &lt;em&gt;bin/zkEnv.sh&lt;/em&gt;). Here is a sample:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tickTime=2000                             # 1 tick = 2000 ms = 2s
initLimit=5                               # 5 ticks
syncLimit=2                               # 2 ticks
dataDir=/var/opt/logger/z1-snapshots      # persistent in-memory snapshots
dataLogDir=/var/opt/logger/z1-txnLogs     # persistent transaction logs
clientPort=2181
autopurge.snapRetainCount=3               # keep lastest 3 versions
autopurge.purgeInterval=2                 # cleanup every 2 hours

4lw.commands.whitelist=*                  # new in 3.5.3, enable all four-letter commands

server.1=logger1:2888:3888                # communication within Zookeeper cluster
server.2=logger2:2888:3888                # port 2888 used to contact leader
server.3=logger3:2888:3888                # port 3888 used to elect leader
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the example above, the server hostname &apos;logger1&apos;, &apos;logger2&apos; and &apos;logger3&apos; is their &lt;em&gt;/etc/hosts&lt;/em&gt; aliases, otherwise use IP addresses.&lt;/p&gt;

&lt;p&gt;According to the configuration example, create &apos;dataDir&apos;, &apos;dataLogDir&apos; and create container aliases.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /var/opt/logger/z1-&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;snapshots,txnLogs&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sudoedit /etc/hosts
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/hosts &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
&amp;gt; 12.34.56.71 logger1
&amp;gt; 12.34.56.72 logger2
&amp;gt; 12.34.56.73 logger3
&amp;gt; EOF
logger@container-logger1 ~ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;ping logger1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We are very close to start ZooKeeper now. Before that, file &lt;em&gt;myid&lt;/em&gt; under &apos;dataDir&apos; must be created to define the unique identifier in accord with &apos;server.X&apos;. Upon startup, a ZooKeeper server gets its identifier by looking up &lt;em&gt;myid&lt;/em&gt;. The only content of this file will be interger X:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;1&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /var/opt/logger/z1-snapshots/myid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For standalone mode, if directive &apos;server.X&apos; is omitted, &apos;myid&apos; should be omitted either.&lt;/p&gt;

&lt;h2 id=&quot;zookeeper-startup&quot;&gt;ZooKeeper Startup&lt;/h2&gt;

&lt;p&gt;ZooKeeper ships with startup scripts &lt;em&gt;bin/zkServer.sh&lt;/em&gt; which sources &lt;em&gt;bin/zkEnv.sh&lt;/em&gt; to set runtime variables. Have a read at the two scripts before executing. Here is an excerpt from &apos;zkServer.sh&apos;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nohup &quot;$JAVA&quot; &quot;-Dzookeeper.log.dir=${ZOO_LOG_DIR}&quot; &quot;-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}&quot; \
-cp &quot;$CLASSPATH&quot; $JVMFLAGS $ZOOMAIN &quot;$ZOOCFG&quot; &amp;gt; &quot;$_ZOO_DAEMON_OUT&quot; 2&amp;gt;&amp;amp;1 &amp;lt; /dev/null &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add &apos;zookeeper/bin&apos; to &apos;PATH&apos;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; /opt/zookeeper/bin/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.cmd
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;PATH=/opt/zookeeper/bin:${PATH}&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.bashrc
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkServer.sh
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkServer.sh print-cmd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From &apos;zkEnv.sh&apos;, the Java max heap size is set to 1000m by variable &apos;ZK_SERVER_HEAP&apos; and &apos;ZK_CLIENT_HEAP&apos;, reflected by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java -Xmx&lt;/code&gt; option. An overwhelming heap size will seriously degrade ZooKeeper performance due to frequent &lt;em&gt;disk swap&lt;/em&gt;. The minimal guarantee is that heap size is &lt;em&gt;smaller&lt;/em&gt; than memory size.&lt;/p&gt;

&lt;h2 id=&quot;zookeeper-logging&quot;&gt;ZooKeeper Logging&lt;/h2&gt;

&lt;p&gt;Basically, ZooKeeper uses &lt;a href=&quot;http://logging.apache.org/log4j/1.2/index.html&quot;&gt;log4j 1.2&lt;/a&gt; as its logging infrastructure. Its configuration file should either be in the &lt;em&gt;working directory&lt;/em&gt; (where &apos;zkServer.sh&apos; is invoked; &lt;strong&gt;not&lt;/strong&gt; the directory where &apos;zkServer.sh&apos; resides), or inclued in JAVA &apos;CLASSPATH&apos;. The default &lt;em&gt;log4j.properties&lt;/em&gt; file resides in &lt;em&gt;conf/&lt;/em&gt; directory which is accessible from &apos;CLASSPATH&apos; as defined in &apos;zkEnv.sh&apos;.&lt;/p&gt;

&lt;p&gt;Variable &apos;ZOO_LOG4J_PROP&apos; defines the log &lt;em&gt;level&lt;/em&gt; and &lt;em&gt;appender&lt;/em&gt; (output destination) of Log4j. By default, they are &apos;INFO&apos; and &apos;CONSOLE&apos; respectively in &apos;zkEnv.sh&apos;. About the priorities of different log levels, read the post &apos;log4j&apos;. Logs appended to &apos;CONSOLE&apos; actually go to STDERR and STDOUT.&lt;/p&gt;

&lt;p&gt;Meanwhile, &apos;zkServer.sh&apos; redirects STDERR and STDOUT to &quot;${ZOO_LOG_DIR}/zookeeper.out&quot; and runs in background. Variable &apos;ZOO_LOG_DIR&apos; is set to &apos;.&apos; (the working directory). If it is ran under the home directory &apos;~&apos;, &lt;em&gt;zookeeper.out&lt;/em&gt; will be created there. Therefore, logs of ZooKeeper are printed to file &lt;em&gt;zookeeper.out&lt;/em&gt; in the working directory.&lt;/p&gt;

&lt;p&gt;Besides, there are other appenders like &apos;ROLLINGFILE&apos; and &apos;TRACEFILE&apos;. Each appender has their own properties defined in &apos;log4j.properties&apos;. The advantage of &apos;ROLLINGFILE&apos; is that logs are rotated by property &apos;MaxFileSize&apos; and property &apos;MaxBackupIndex&apos;. Multiple appenders can be turned on or off concurrently. For example, both &apos;CONSOLE&apos; and &apos;ROLLINGFILE&apos; can be turned on. If &apos;CONSOLE&apos; is turned off, &apos;zookeeper.out&apos; is always empty.&lt;/p&gt;

&lt;p&gt;Hence, start ZooKeeper with specified &apos;ZOO_LOG_DIR&apos; and &apos;ZOO_LOG4J_PROP&apos;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;ZooKeeper logs is located at &lt;em&gt;/var/opt/logger/z1-logs&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Choose &apos;ROLLINGFILE&apos; appender.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /var/opt/logger/z1-logs
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ ZOO_LOG_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/var/opt/logger/z1-logs&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ZOO_LOG4J_PROP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;INFO,ROLLINGFILE&quot;&lt;/span&gt; zkServer.sh print-cmd
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export ZOO_LOG_DIR=&quot;/var/opt/logger/z1-logs&quot; ZOO_LOG4J_PROP=&quot;INFO,ROLLINGFILE&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.bashrc
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkServer.sh print-cmd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, the setup of the first ZooKeeper server is completed. We will commit &lt;em&gt;logger1&lt;/em&gt; on which &lt;em&gt;logger2&lt;/em&gt; and &lt;em&gt;logger3&lt;/em&gt; is created.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;^P-^Q
logger@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker stop logger1

logger@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker commit &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;logger&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;copy logger1&quot;&lt;/span&gt; logger1 centos-7.6:logger1
logger@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker image &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Recall that, each container has a hostname alias associated with a fixed IP in &lt;em&gt;/etc/hosts&lt;/em&gt;. So always start the containers in the &lt;em&gt;exact order&lt;/em&gt;: &lt;em&gt;logger1&lt;/em&gt;, &lt;em&gt;logger2&lt;/em&gt; and &lt;em&gt;logger3&lt;/em&gt;, such that the Docker daemon assign IPs in order.&lt;/p&gt;

&lt;p&gt;Start and create the containers in order:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker start logger1

logger@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; logger2 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;,source&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/opt/logger,target&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/opt/logger &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; /var/opt/logger &lt;span class=&quot;nt&quot;&gt;--net&lt;/span&gt; bridge &lt;span class=&quot;nt&quot;&gt;--add-host&lt;/span&gt; host-eth0:&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOSTIP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; root:root centos-7.6:logger1 bash
logger@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; logger3 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;,source&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/opt/logger,target&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/opt/logger &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; /var/opt/logger &lt;span class=&quot;nt&quot;&gt;--net&lt;/span&gt; bridge &lt;span class=&quot;nt&quot;&gt;--add-host&lt;/span&gt; host-eth0:&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOSTIP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; root:root centos-7.6:logger1 bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attach to &lt;em&gt;logger2&lt;/em&gt; aned &lt;em&gt;logger3&lt;/em&gt;, and adjust the following items:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/etc/sudoers.d/zk
~/.bashrc
conf/zoo.cfg ; mkdir -p /var/opt/logger/z2-{logs,snapshots,txnLogs}
echo &apos;2&apos; &amp;gt; /var/opt/logger/z2-snapshots/myid
zkServer.sh print-cmd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, it is time to start the servers. A customized configuration file can be supplied to the command line upon starting (i.e. for debugging) to override the default &lt;em&gt;conf/zoo.cfg&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkServer.sh start &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;/path/to/zoo.cfg]

logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkServer.sh status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, it may report:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error contacting service. It is probably not running.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This means the ZooKeeper culster are not yet established (i.e. leader election ongoing) though each server is already running. Then try other methods:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eF&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;[z]ookeeper&apos;&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt; ~/var/opt/logger/z1-snapshots/zookeeper.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;zookeeper.log&lt;/em&gt; prints many useful information like configuration pathname, hosts aliases resolution, &lt;em&gt;autopurge&lt;/em&gt; arguments, tick and timeout, peer election process etc. Specially, there is a line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Created server with tickTime 2000 minSessionTimeout 4000 maxSessionTimeout 40000 datadir /var/opt/logger/z1-txnLogs/version-2 snapdir /var/opt/logger/z1-snapshots/version-2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;datadir&lt;/em&gt; refers to the location where transaction logs are stored; &lt;em&gt;snapdir&lt;/em&gt; refers to that of in-memory snapshots. Please pay attention that these two name is different than those in &lt;em&gt;zoo.cfg&lt;/em&gt;. &lt;em&gt;datadir&lt;/em&gt; corresponds to directive &apos;dataLogDir&apos; while &apos;snapdir&apos; corresponds to directive &apos;dataDir&apos;. Read &lt;a href=&quot;https://zookeeper.apache.org/doc/r3.4.14/api/org/apache/zookeeper/server/PurgeTxnLog.html&quot;&gt;PurgeTxnLog API&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;zookeeper-status&quot;&gt;&lt;a href=&quot;https://zookeeper.apache.org/doc/r3.4.14/zookeeperAdmin.html&quot;&gt;ZooKeeper Status&lt;/a&gt;&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkServer.sh
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pgrep &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; logger &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;-ac&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;java.*\/home\/logger\/zookeeper\/bin&apos;&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkServer.sh status

&lt;span class=&quot;c&quot;&gt;# zkServer.sh status&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ZooKeeper JMX enabled by default&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Using config: /opt/zookeeper/bin/../conf/zoo.cfg&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Mode: follower&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &apos;Mode&apos; line tells if a server is a leader or a follower.&lt;/p&gt;

&lt;p&gt;Apart from the script wrapper &apos;zkServer.sh&apos;, ZooKeeper can respond to a predefined set of &lt;a href=&quot;https://zookeeper.apache.org/doc/r3.4.14/zookeeperAdmin.html#sc_zkCommands&quot;&gt;four-letter commands&lt;/a&gt;. We issue the commands to servers&apos; (TCP/UDP) sockets via &lt;em&gt;telnet&lt;/em&gt; or &lt;em&gt;nc&lt;/em&gt;, at the client port (default 2181):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; nmap-ncat.x86_64
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nc localhost 2181 &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;dump&apos;&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;srvr | stat | envi&apos;&lt;/span&gt; | nc localhost 2181
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From ZooKeeker 3.5.3 onwards, by default only &apos;srvr&apos; is enabled. We should configure property &apos;4lw.commands.whitelist&apos; to turn on desired commands.&lt;/p&gt;

&lt;p&gt;Another wrapper script &apos;zkCli.sh&apos; connects to servers and perform filesystem-like operations:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkCli.sh &lt;span class=&quot;nt&quot;&gt;-server&lt;/span&gt; localhost:2181 &lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;# print help message&lt;/span&gt;

logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkCli.sh &lt;span class=&quot;nt&quot;&gt;-server&lt;/span&gt; localhost:2181          &lt;span class=&quot;c&quot;&gt;# interactive ZooKeeper shell&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# [zk: localhost:2181(CONNECTED) 0] help                         # print help message&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [zk: localhost:2181(CONNECTED) 0] ls /                         # list the &apos;root&apos; znode&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [zk: localhost:2181(CONNECTED) 0] create /zk_test my_data      # creat a new znode directory&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [zk: localhost:2181(CONNECTED) 0] ls /&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [zk: localhost:2181(CONNECTED) 0] set /zk_test my_new_data&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [zk: localhost:2181(CONNECTED) 0] get /zk_test&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [zk: localhost:2181(CONNECTED) 0] delete /zk_test&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [zk: localhost:2181(CONNECTED) 0] ls /&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [zk: localhost:2181(CONNECTED) 0] quit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;zookeeper-storage&quot;&gt;&lt;a href=&quot;https://zookeeper.apache.org/doc/r3.4.14/zookeeperAdmin.html#sc_administering&quot;&gt;ZooKeeper Storage&lt;/a&gt;&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;For a long running production system, persistent storage must be managed manually or automatically by &lt;em&gt;autopurge&lt;/em&gt; mentioned above.&lt;/li&gt;
  &lt;li&gt;Recall that logs of ZooKeeper itself is rotated automatically by &apos;ROLLINGFILE&apos;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To manually purge history snapshots and related transaction logs:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/zookeeper/
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;java &lt;span class=&quot;nt&quot;&gt;-cp&lt;/span&gt; zookeeper-3.4.14.jar:lib/slf4j-api-1.7.25.jar:lib/slf4j-log4j12-1.7.25.jar:lib/log4j-1.2.17.jar:conf org.apache.zookeeper.server.PurgeTxnLog &amp;lt;datadir&amp;gt; &amp;lt;snapdir&amp;gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &amp;lt;count&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;datadir&lt;/em&gt; (&apos;dataLogDir&apos;) and &lt;em&gt;snapdir&lt;/em&gt; (&apos;dataDir&apos;) can be found either from &lt;em&gt;zookeeper.log&lt;/em&gt;, in &lt;em&gt;zoo.cfg&lt;/em&gt;, or by the four-letter command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conf&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n &amp;lt;count&amp;gt;&lt;/code&gt; means to keep the last &apos;count&apos; snapshots and transaction logs, which should be no less than 3 conventionally.&lt;/li&gt;
  &lt;li&gt;Make sure the correct classpath is provided.&lt;/li&gt;
  &lt;li&gt;Create a &lt;em&gt;cron&lt;/em&gt; job.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Actually, ZooKeeper provides a built-in &apos;zkCleanup.sh&apos; script to wrap the Java command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkCleanup.sh &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&apos;zkCleanup.sh&apos; accepts the same arguments as above and makes cron jobs much eaiser. However, ZooKeeper 3.4.0 onwards already supports &lt;em&gt;autopurge&lt;/em&gt;, why not just use the built-in feature?&lt;/p&gt;

&lt;h2 id=&quot;stop-zookeeper&quot;&gt;Stop ZooKeeper&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkServer.sh stop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;zookeeper-systemd-unit&quot;&gt;ZooKeeper Systemd Unit&lt;/h2&gt;

&lt;p&gt;Read the post &lt;a href=&quot;https://blog.redbranch.net/2018/04/19/zookeeper-install-on-centos-7/&quot;&gt;Zookeeper install on CentOS 7&lt;/a&gt; first.&lt;/p&gt;

&lt;h2 id=&quot;zookeeper-advanced-tips&quot;&gt;Zookeeper Advanced Tips&lt;/h2&gt;

&lt;h3 id=&quot;dynamic-reconfiguration&quot;&gt;Dynamic Reconfiguration&lt;/h3&gt;

&lt;p&gt;From 3.5.0 onwards, directives &apos;clientPort&apos; and &apos;clientPortAddress&apos; can be integrated into the &apos;Server.X&apos; directive as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# server.X = &amp;lt;address1&amp;gt;:port1:port2[:role];[&amp;lt;client port address&amp;gt;:]&amp;lt;client port&amp;gt;

server.1 = 12.34.56.78:2888:3888;2181
server.2 = 12.34.56.78:2888:3888:participant;2181
server.3 = 192.168.0.105:2888:3888:observer;12.34.56.78:2181
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dynamic Reconfiguration means to update confiuration on the fly without restarting ZooKeeper servers.&lt;/p&gt;

&lt;h3 id=&quot;observer-server&quot;&gt;Observer Server&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, at least a quorum of the active servers are synched on a &apos;write&apos; operation. However, this requirement make it hard to scale the number of ZooKeeper servers and/or the number of clients as write sync takes time and resources.&lt;/p&gt;

&lt;p&gt;ZooKeeper now introduces a new type of server called &lt;em&gt;observer&lt;/em&gt; to improve scalability, distinguished from the common &lt;em&gt;participant&lt;/em&gt; servers. Observers are almost the same as participant followers except that they does not participate in write sync and only receive the sync results.&lt;/p&gt;

&lt;p&gt;Therefore, we can increase the number of observers as much as we like without harming the write sync performance. To specify an observer server, the configuration looks like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;peerType=observer
server.1=localhost:2888:3888:observer;2181
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;kafka&quot;&gt;Kafka&lt;/h1&gt;

&lt;h2 id=&quot;kafka-installation&quot;&gt;Kafka Installation&lt;/h2&gt;

&lt;p&gt;Like that of ZooKeeper, the installation process of Kafka is quite straightforward, download and untar.&lt;/p&gt;

&lt;p&gt;A kafka distribution is named as &apos;kafka_scalaVersion-kafkaVersion.tgz`. Each Kafka version may have multiple scala disbributions, and vice versa. As of the post, the Scala version is 2.12 while Kafka version is 2.2.0.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-O&lt;/span&gt; /var/opt/logger/ https://www-eu.apache.org/dist/kafka/2.2.0/kafka_2.12-2.2.0.tgz
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xzpvf&lt;/span&gt; /var/opt/logger/kafka_2.12-2.2.0.tgz &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; /opt/
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sv&lt;/span&gt; kafka_2.12-2.2.0 kafka
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chown&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-R&lt;/span&gt; logger:logger kafka/
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ll kafka/config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;kafka-configuration&quot;&gt;Kafka Configuration&lt;/h2&gt;

&lt;p&gt;Now configure &lt;a href=&quot;https://kafka.apache.org/documentation/#configuration&quot;&gt;server.properties&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
# similar to ZooKeeper &apos;myid&apos;; a unique integer
broker.id=1

# comma-separated listeners
listeners=PLAINTEXT://0.0.0.0:9092,EDGE://1.2.3.4:9093,USA://5.6.7.8:9094
# advertised listners
advertised.listeners=PLAINTEXT://0.0.0.0:9092,EDGE://1.2.3.4:9093,USA://5.6.7.8:9094
# listner for inter-broker communication
inter.broker.listener.name=PLAINTEXT
# listener name mapping to security prototol
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL,EDGE:PLAINTEXT,USA:PLAINTEXT

# commit logs location; high speed SSDs
#log.dir=/tmp/kafka-logs
# default to &apos;log.dir&apos;
log.dirs=/home/zk/kafka/commitLogs

# default partitions per topic
num.partitions=3

# replication factor for internal topics like &quot;__consumer_offsets&quot;
offsets.topic.replication.factor=2
transaction.state.log.replication.factor=2
transaction.state.log.min.isr=2

# ZooKeeper servers
zookeeper.connect=zk1:2181,zk2:2181,zk3:2181
zookeeper.connection.timeout.ms=3000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;listeners&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Listeners are what interfaces a Kafka broker bind to.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;The directive is a list of comma-separated listeners. Each listener is actually a TCP socket on the broker and is associated with a name, hostname/IP, and port.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# listeners = listener_name://my.host.name:port
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Specify hostname as &apos;0.0.0.0&apos; to bind to all interfaces. Leave hostname empty to bind to the &lt;em&gt;default&lt;/em&gt; interface. A hostname can be resolved to multiple IPs to do load balance. If this directive is not set, it defaults to &apos;PLAINTEXT://0.0.0.0:9092&apos;.&lt;/p&gt;

    &lt;p&gt;A listener should be mapped to a security protocol by its name for connection authentication, and thus often named after a security protocol:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ name to security protocol map
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;So we cannot define two listeners with the same name.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# error: two listners with the same name
listeners=PLAINTEXT://192.168.1.100:9092,PLAINTEXT://12.34.56.78:9092
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Multiple listeners MUST have different ports.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;advertised.listeners&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Advertised listeners are what interfaces a client (producer/consumer) connects to.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;A listener is firtly published to the ZooKeeper cluster, then spreaded to all other Kafka brokers, and finally to clients. The limitation is that a listener can be advertised only once.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Communication within the cluster brokers and can be achieved through any defined listeners. Clients get the cluster metadata from any defined listeners as well.&lt;/li&gt;
      &lt;li&gt;However, read and/or write connections are only done through advertised listeners. Hence, usually we advertise listeners with public IP.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;listeners=PLAINTEXT://0.0.0.0:9092
   
advertised.listeners=PLAINTEXT://12.34.56.78:9092
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The design of multiple listeners &lt;a href=&quot;https://cwiki.apache.org/confluence/display/KAFKA/KIP-103%3A+Separation+of+Internal+and+External+traffic&quot;&gt;defined and/or advertised&lt;/a&gt; gives a fair amount of flexibility. For example, we can advertise a listener for internal clients while another one for external clients. Additionally, a separate advertised listener for replicated partition traffic is desired. Directive &apos;inter.broker.listener.name&apos; can be set to a listener for traffic between brokers like:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;inter.broker.listener.name=PLAINTEXT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If not properly advertised, a client may fail to produce or consumer data. For example, if a listener is bound to &apos;0.0.0.0:9092&apos; but only advertise the LAN address &apos;192.168.1.100:9092&apos;, clients could still initiate a connection to the broker through &apos;12.34.56.78:9092&apos; (public IP), fetching metadata about brokers. When it comes to read and/or write data, clients can only contact the advertised addresses enclosed in metadata. That demonstrates the difference between &lt;a href=&quot;https://rmoff.net/2018/08/02/kafka-listeners-explained/&quot;&gt;reachable socket and reachable service&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;We CANNOT advertise a listener with &apos;0.0.0.0&apos;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&apos;log.dirs&apos; is a list comma-separated locations to store commit logs. If not set, it &lt;a href=&quot;https://stackoverflow.com/q/40369238&quot;&gt;defaults to &apos;log.dir&apos;&lt;/a&gt; that is a single location. &apos;log.dir&apos; defaults to &lt;em&gt;/tmp/kafka-logs&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;ZooKeeper listens for Kafka connections at port 2181; Kafka listens at port 9092.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;start-kafka&quot;&gt;Start Kafka&lt;/h2&gt;

&lt;p&gt;Before starting brokers, create directories and change &apos;PATH&apos;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /var/opt/logger/k1-logs
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;PATH=/opt/kafka/bin:${PATH}&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Kafka has a bunch of built-in scripts, of which &apos;kafka-server-start.sh&apos; and &apos;kafka-run-class.sh&apos; are responsible for starting the service. In the scripts, there is a special variable &apos;base_dir&apos; setting the base directory (recall &apos;ZOO_LOG_DIR&apos; of ZooKeeper) that defaults to Kafka installation directory.&lt;/p&gt;

&lt;p&gt;Similar to ZooKeeper, Kafka also utilize &apos;Log4j&apos; to trace broker logs affected by environment variables &apos;LOG_DIR&apos;, and &apos;KAFKA_LOG4J_OPTS&apos;, and Java property &apos;kafka.logs.dir&apos;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Script &apos;kafka-server-start.sh&apos;:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Log4j property file&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;KAFKA_LOG4J_OPTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-Dlog4j.configuration=file:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$base_dir&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/../config/log4j.properties&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Script &apos;kafka-run-class.sh&apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;LOG_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$base_dir&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/logs&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From the definition, broker logs default to &lt;em&gt;kafka/logs&lt;/em&gt; where Kafka is installed, including &apos;server.log&apos;, &apos;state-change.log&apos; and &apos;controller.log&apos; (recording leader election).&lt;/p&gt;

&lt;p&gt;We can just leave brokers logging to the defauts. OK, start the server:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-server-start.sh
&lt;span class=&quot;c&quot;&gt;# USAGE: /opt/kafka/bin/kafka-server-start.sh [-daemon] server.properties [--override property=value]*&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# explictly provide &apos;server.properties&apos;&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-server-start.sh &lt;span class=&quot;nt&quot;&gt;-daemon&lt;/span&gt; /opt/kafka/config/server.properties
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-daemon&lt;/code&gt; option put Kafka into background.&lt;/li&gt;
  &lt;li&gt;Unlike ZooKeeper, Kafka requires explicit pathname of property file.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--override&lt;/code&gt; changes default properties. For example, to change the location of broker logs, either modify property &apos;kafka.logs.dir&apos; or environment variable &apos;LOG_DIR&apos;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /var/opt/br1-logs
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ LOG_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/opt/br1-logs kafka-server-start.sh ...
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-server-start.sh ... &lt;span class=&quot;nt&quot;&gt;--override&lt;/span&gt; kafka.logs.dir&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/opt/br1-logs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Repeat the above setup for the other two Kafka servers.&lt;/p&gt;

&lt;h2 id=&quot;kafka-status&quot;&gt;Kafka Status&lt;/h2&gt;

&lt;p&gt;We can verify if the server was started correctly through ZooKeeper dump:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ $ ps -eF | grep &apos;[k]akfka&apos;
logger@container-logger1 ~ $ ss -npelt
logger@container-logger1 ~ $ pgrep -u logger -P 1 -ac -f &apos;java.*\/home\/logger\/kafka\/bin&apos;
logger@container-logger1 ~ $ tail -F /var/opt/br1-logs/server.log

logger@container-logger1 ~ $ nc localhost 2181 &amp;lt;&amp;lt;&amp;lt; &quot;dump&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is a sample output:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SessionTracker dump:
Session Sets (4):
0 expire at Sat Feb 21 00:11:04 UTC 1970:
0 expire at Sat Feb 21 00:11:06 UTC 1970:
0 expire at Sat Feb 21 00:11:08 UTC 1970:
3 expire at Sat Feb 21 00:11:10 UTC 1970:
        0x2010197720b0000
        0x301019c5afd0000
        0x301019c5afd0001
ephemeral nodes dump:
Sessions with Ephemerals (3):
0x301019c5afd0000:
        /brokers/ids/2
0x301019c5afd0001:
        /brokers/ids/3
0x2010197720b0000:
        /controller
        /brokers/ids/1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From the excerpt, we know ZooKeeper create an individual znode for each Kafka server, within the namespace tree. To further investigate:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkCli.sh &lt;span class=&quot;nt&quot;&gt;-server&lt;/span&gt; localhost:2181 &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /

&lt;span class=&quot;c&quot;&gt;# [cluster, controller_epoch, controller, brokers, zookeeper, admin, isr_change_notification, consumers, log_dir_event_notification, latest_producer_id_block, config]&lt;/span&gt;

logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkCli.sh &lt;span class=&quot;nt&quot;&gt;-server&lt;/span&gt; localhost:2181 get /brokers/ids/1
&lt;span class=&quot;c&quot;&gt;# [1, 2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;stop-kafka&quot;&gt;Stop Kafka&lt;/h2&gt;

&lt;p&gt;When a broker is gracefully stopped, it may take advantage of:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Commit logs are synced to disk to avoid logs recovery upon restart.&lt;/p&gt;

    &lt;p&gt;Log recovery taks time as checksum validation is required for all entries in the tail of the log.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Partitions this broker is the leader for are synchronized to followers, which significantly increase the process of new leader election - leadership migration.&lt;/p&gt;

    &lt;p&gt;This requires that the topic replication factor is greater than 1 (i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--replication-factor=2&lt;/code&gt;), otherwise this single leader would sync the partitions nowhere and commit logs would be unavailable! A replication factor greater than 1 is always what we want!&lt;/p&gt;

    &lt;p&gt;Another requirement, is directive &lt;em&gt;controlled.shutdown.enable&lt;/em&gt; is set to &lt;em&gt;true&lt;/em&gt; (default).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To gracefully stop a broker:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-server-stop.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The script does &lt;em&gt;not&lt;/em&gt; accept any options and just sends &apos;SIGTERM&apos; signal to the Kafka process. So don&apos;t try to pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--help&lt;/code&gt; as it inevitably stops the service.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Stop Kafka before ZooKeeper;&lt;/li&gt;
  &lt;li&gt;It takes time to stop Kafka cluster, so wait for while!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;topic-creation&quot;&gt;Topic Creation&lt;/h2&gt;

&lt;p&gt;Kafka provides a simple console producer and consumer script, quite handy for test.&lt;/p&gt;

&lt;p&gt;Before Kafka version 0.9, built-in scripts require the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--zookeeper&lt;/code&gt; to specify one or more ZooKeeper servers to connect to as &lt;em&gt;offset&lt;/em&gt; data is stored within ZooKeeper. The offset data is now moved into Kafka itself (the built-in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__consumer_offset&lt;/code&gt; topic). So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--zookeeper&lt;/code&gt; option is &lt;a href=&quot;https://stackoverflow.com/q/46173003&quot;&gt;depcreated&lt;/a&gt; in favor of option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--bootstrap-server&lt;/code&gt; using brokers.&lt;/p&gt;

&lt;p&gt;Firstly, create a test topic:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ $ kafka-topics.sh
logger@container-logger1 ~ $ kafka-topics.sh --zookeeper logger1:2181,logger2:2181 --list

logger@container-logger1 ~ $ kafka-topics.sh --bootstrap-server logger1:9092,logger2:9092,logger3:9092 --create --replication-factor 2 --partitions 3 --topic test-topic
logger@container-logger1 ~ $ kafka-topics.sh --bootstrap-server logger2:9092 --list
logger@container-logger1 ~ $ kafka-topics.sh --bootstrap-server logger2:9092 --describe --topic test-topic

# Topic:test-topic        PartitionCount:3        ReplicationFactor:2     Configs:segment.bytes=1073741824
#         Topic: test-topic       Partition: 0    Leader: 2       Replicas: 2,3   Isr: 2,3
#         Topic: test-topic       Partition: 1    Leader: 3       Replicas: 3,1   Isr: 3,1
#         Topic: test-topic       Partition: 2    Leader: 1       Replicas: 1,2   Isr: 1,2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--replication-factor&lt;/code&gt; defines the number of replicas.&lt;/p&gt;

    &lt;p&gt;It is a must!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--partitions&lt;/code&gt; overrides &apos;num.partitions&apos; in &apos;server.properties&apos;.&lt;/li&gt;
  &lt;li&gt;The topic has 3 partitions.&lt;/li&gt;
  &lt;li&gt;From the output of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--describe&lt;/code&gt;, replicas in all followers are in-sync replicas.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;console-producer-and-consumer&quot;&gt;Console Producer and Consumer&lt;/h2&gt;

&lt;p&gt;Next, we launch a consumer on the topic:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-console-consumer.sh
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-console-consumer.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger2:9092 &lt;span class=&quot;nt&quot;&gt;--topic&lt;/span&gt; test-topic &lt;span class=&quot;nt&quot;&gt;--from-beginning&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No explicit consumer group is created here. By default, &apos;kafka-console-consumer.sh&apos; will create a random group ID through Java consumer API.&lt;/p&gt;

&lt;p&gt;Then start a producer with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--broker-list&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger2 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-console-producer.sh &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
logger@container-logger2 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-console-producer.sh &lt;span class=&quot;nt&quot;&gt;--broker-list&lt;/span&gt; logger1:9092,logger2:9092,logger3:9092 &lt;span class=&quot;nt&quot;&gt;--topic&lt;/span&gt; test-topic

&lt;span class=&quot;c&quot;&gt;# hello, world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now everything typed in the producer console will be automatically printed in the consumer console. Check partitions:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkCli.sh &lt;span class=&quot;nt&quot;&gt;-server&lt;/span&gt; localhost:2181 get /brokers/topics/test-topic/partitions/1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^C&lt;/code&gt; to stop the consumer and producer.&lt;/p&gt;

&lt;h2 id=&quot;consumer-group&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/a/36910791&quot;&gt;Consumer Group&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Let&apos;s play around consumer group.&lt;/p&gt;

&lt;p&gt;Firstly, we want a list of existing consumer groups either by ZooKeeper interface or by Kafka interfaces.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zkCli.sh &lt;span class=&quot;nt&quot;&gt;-server&lt;/span&gt; localhost:2181 &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /consumers

&lt;span class=&quot;c&quot;&gt;# &amp;lt; 0.9: consumers contact ZooKeeper&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-consumer-groups.sh &lt;span class=&quot;nt&quot;&gt;--zookeeper&lt;/span&gt; logger1:2181  &lt;span class=&quot;nt&quot;&gt;--list&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &amp;gt;= 0.9: consumers contact Kafka directly by Java consumer API&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-consumer-groups.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--list&lt;/span&gt;

logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-consumer-groups.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--describe&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--group&lt;/span&gt; consumer-group-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, we try to create an explicit consumer group. A consumer can join an existing group (implicit default included) or create a new one:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--group consumer-group-name1&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;This is the most obvious option.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--consumer.config filename&lt;/code&gt;;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /path/to/filename
group.id=consumer-group-name2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--consumer-property group.id=consumer-group-name3&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;These two options are done through direct Java property.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If the provided name exsit, then the new consumer join the group, otherwise the group would be created.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-console-consumer.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--topic&lt;/span&gt; test-topic &lt;span class=&quot;nt&quot;&gt;--group&lt;/span&gt; consumer-group-12345
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-console-consumer.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--topic&lt;/span&gt; test-topic &lt;span class=&quot;nt&quot;&gt;--consumer&lt;/span&gt;.config consumer-group-12346
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-console-consumer.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--topic&lt;/span&gt; test-topic &lt;span class=&quot;nt&quot;&gt;--consumer-property&lt;/span&gt; group.id&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;consumer-group-12347

logger@container-logger2 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-consumer-groups.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger2:9092 &lt;span class=&quot;nt&quot;&gt;--describe&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--group&lt;/span&gt; consumer-group-12345
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;kafka-security&quot;&gt;Kafka Security&lt;/h2&gt;

&lt;p&gt;Post &lt;a href=&quot;https://medium.com/@stephane.maarek/introduction-to-apache-kafka-security-c8951d410adf&quot;&gt;introduction-to-apache-kafka-security&lt;/a&gt; gives a clear outline on Kafka security mechanisms. It recommends &lt;a href=&quot;https://docs.confluent.io/4.0.0/kafka/authentication_sasl_scram.html&quot;&gt;SASL/SCRAM&lt;/a&gt; method (Zookeeper only supports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SASL/DIGEST-MD5&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Kafka uses &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/technotes/guides/security/jaas/JAASRefGuide.html&quot;&gt;Java Authentication and Authorization Service (JAAS)&lt;/a&gt; for both server side security setup and client side authentication.&lt;/p&gt;

&lt;p&gt;There are &lt;a href=&quot;https://docs.confluent.io/platform/current/kafka/authentication_sasl/index.html#client-jaas-configurations&quot;&gt;two ways&lt;/a&gt; to &lt;a href=&quot;https://stackoverflow.com/a/45757197/2336707&quot;&gt;provide JAAS data&lt;/a&gt; (e.g., SASL).&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Configuration property string in &lt;a href=&quot;#kafka-configuration&quot;&gt;.properties&lt;/a&gt; like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sasl.jaas.config=&lt;/code&gt;. This is the recommended method.&lt;/p&gt;

    &lt;p&gt;Below is an example. Please make sure the trailing semi-colon is present.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username=&quot;(username)&quot; password=&quot;(password)&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Built-in CLI clients can automatically detect the security setup. If not, add option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--command-string&lt;/code&gt; to &lt;em&gt;kafka-topics.sh&lt;/em&gt;, or option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--producer.config&lt;/code&gt; to &lt;em&gt;kafka-console-producer.sh&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;JAAS file. For example, on server side, we can pass the static file as below.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;KAFKA_OPTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-Djava.security.auth.login.config=/path/to/kafka_jaas.conf&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;dynamic-update-mode&quot;&gt;Dynamic Update Mode&lt;/h2&gt;

&lt;p&gt;From Kafka 1.1 onwards, directives could be &lt;a href=&quot;https://kafka.apache.org/documentation/#dynamicbrokerconfigs&quot;&gt;updated/overriden dynamically&lt;/a&gt;. The &lt;a href=&quot;https://kafka.apache.org/documentation/#configuration&quot;&gt;Broker&apos;s Dynamic Update Mode&lt;/a&gt; column may be:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;read-only: requires restart for update;&lt;/li&gt;
  &lt;li&gt;per-broker: can be updated for each broker on the fly;&lt;/li&gt;
  &lt;li&gt;cluster-wide: can be updated for all brokers; may also be updated for an individual broker.&lt;/li&gt;
  &lt;li&gt;Some directives can be changed dynamically per-topic, like the directive &apos;num.partitions&apos;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To get a list of supported directives on command line:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-configs.sh &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To check current broker configuration:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-configs.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--entity-type&lt;/span&gt; brokers &lt;span class=&quot;nt&quot;&gt;--entity-name&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;--describe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Change number of cleanup threads for commit logs:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# per-broker&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-configs.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--entity-type&lt;/span&gt; brokers &lt;span class=&quot;nt&quot;&gt;--entity-name&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;--alter&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add-config&lt;/span&gt; log.cleaner.threads&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-configs.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--entity-type&lt;/span&gt; brokers &lt;span class=&quot;nt&quot;&gt;--entity-name&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;--describe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To apply the change to all brokers, use option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--entity-default&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cluster-wide&lt;/span&gt;
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-configs.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--entity-type&lt;/span&gt; brokers &lt;span class=&quot;nt&quot;&gt;--entity-default&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--alter&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add-config&lt;/span&gt; log.cleaner.threads&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-configs.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--entity-type&lt;/span&gt; brokers &lt;span class=&quot;nt&quot;&gt;--entity-default&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--describe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To revert the dynamic modification and restore the static value configured:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-configs.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--entity-type&lt;/span&gt; brokers &lt;span class=&quot;nt&quot;&gt;--entity-name&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;--alter&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--delete-config&lt;/span&gt; log.cleaner.threads
logger@container-logger1 ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kafka-configs.sh &lt;span class=&quot;nt&quot;&gt;--bootstrap-server&lt;/span&gt; logger1:9092 &lt;span class=&quot;nt&quot;&gt;--entity-type&lt;/span&gt; brokers &lt;span class=&quot;nt&quot;&gt;--entity-name&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;--describe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A directive may be configured at multiple levels in the follow order of precedence:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Dynamic per-broker;&lt;/li&gt;
  &lt;li&gt;Dynamic cluster-wide;&lt;/li&gt;
  &lt;li&gt;Static in &apos;server.properties&apos;;&lt;/li&gt;
  &lt;li&gt;Kafka default.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Log4j</title>
   <link href="/2019/04/11/log4j/"/>
   <updated>2019-04-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/04/11/log4j</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#abcs&quot; id=&quot;markdown-toc-abcs&quot;&gt;ABCs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;p&gt;There are three core components of Log4j:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Logger: log level priority.&lt;/p&gt;

    &lt;p&gt;From highest to lowest:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;OFF &amp;gt; FATAL &amp;gt; ERROR &amp;gt; WARN &amp;gt; INFO &amp;gt; DEBUG &amp;gt; TRACE &amp;gt; ALL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;The lower a level is, the more detailed is the log.&lt;/li&gt;
      &lt;li&gt;When a particular log level is set, logs of higher levels are also printed while logs of lower levels are not. Specailly, &apos;OFF&apos; turns off log completely while &apos;ALL&apos; prints everything.&lt;/li&gt;
      &lt;li&gt;Use &apos;ERROR&apos; or &apos;WARN&apos; to avoid demanding log storage in practice.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Appender: determine destinations of log output, console, files, remote socket servers, Apache Flume, JMS, remote UNIX Syslog daemons, and various database APIs etc.&lt;/p&gt;

    &lt;p&gt;Often, log to either console or file.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Layout: log format.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Filebeat</title>
   <link href="/2019/04/11/filebeat/"/>
   <updated>2019-04-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/04/11/filebeat</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;
</content>
 </entry>
 
 <entry>
   <title>Flume</title>
   <link href="/2019/04/10/flume/"/>
   <updated>2019-04-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/04/10/flume</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#abcs&quot; id=&quot;markdown-toc-abcs&quot;&gt;ABCs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configuration&quot; id=&quot;markdown-toc-configuration&quot;&gt;Configuration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#starting-an-agent&quot; id=&quot;markdown-toc-starting-an-agent&quot;&gt;Starting an Agent&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;abcs&quot;&gt;&lt;a href=&quot;https://flume.apache.org/FlumeUserGuide.html&quot;&gt;ABCs&lt;/a&gt;&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;flume [c] an inclined channel for conveying water (as for power); a ravine or gorge with a stream running through it.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Apache Flume is a &lt;em&gt;distributed&lt;/em&gt; system for &lt;em&gt;collecting&lt;/em&gt;, &lt;em&gt;aggregating&lt;/em&gt; and moving log data from many different sources to a &lt;em&gt;centralized&lt;/em&gt; data store.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Require Java Runtime Environment (JRE) - 1.8 or later.&lt;/li&gt;
  &lt;li&gt;A Flume &lt;em&gt;event&lt;/em&gt; is byte payload with optional string atrributes - also called Flume &lt;em&gt;data&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A Flume &lt;em&gt;agent&lt;/em&gt; is a JVM process consisting of three components: &lt;em&gt;sources&lt;/em&gt;, &lt;em&gt;channels&lt;/em&gt;, and &lt;em&gt;sinks&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/flume-flow.png&quot; alt=&quot;Flume Flow&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When a source receives an event, it stores it into one or more channels. The channel keeps the event until it is consumed by a Flume sink.&lt;/p&gt;

    &lt;p&gt;Channels are &lt;em&gt;passive&lt;/em&gt; buffers between sources and sinks: neither send nor pull events proactively.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Multiple agents can be connected to form a multi-hop events flow. For example, an &lt;em&gt;avro&lt;/em&gt;-typed source can recive external events from an &lt;em&gt;avro&lt;/em&gt;-typed sink, using &lt;a href=&quot;https://en.wikipedia.org/wiki/Remote_procedure_call&quot;&gt;RPC&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Multi-agent flow:&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/flume-multi-agent.png&quot; alt=&quot;flume-multi-agent&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;Consolidation:&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/flume-consolidation.png&quot; alt=&quot;flume-consolidation&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;Multiplexing:&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/flume-multiplexing.png&quot; alt=&quot;flume-multiplexing&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;/h1&gt;

&lt;p&gt;Usually, Flume configuration files end with &lt;em&gt;.properties&lt;/em&gt; suffix.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Always keep in mind that, an agent may have multiple sources, multiple channels, and multiple sinks. How these multiple objects are configured to cooperate are important!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Each source, channel and sink has a &lt;em&gt;type&lt;/em&gt; property.&lt;/p&gt;

    &lt;p&gt;For example, a source type may be &lt;em&gt;exec&lt;/em&gt;; a channel type may be &lt;em&gt;memory&lt;/em&gt;; a sink type may be &lt;em&gt;avro&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Other properties are set accordingly.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A Flume source can have an &lt;em&gt;interceptors&lt;/em&gt; property. Interceptors are used to tranform recevied events before putting them onto a channel.&lt;/p&gt;

    &lt;p&gt;For example, an interceptor may be chosen to translate raw event data into Json format.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;my_agent.sources.r12a.type = exec
my_agent.sources.r12a.channels=c12
my_agent.sources.r12a.command=tail -F /var/log/server.log
my_agent.sources.r12a.logStdErr = true
my_agent.sources.r12a.batchSize = 100
my_agent.sources.r12a.interceptors=log2Json
my_agent.sources.r12a.interceptors.log2Json.type=Flume.log2Json$Builder
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Flume.log2Json$Builder&lt;/code&gt; is an external Java class.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Multiple sinks can be grouped (&lt;em&gt;sink group&lt;/em&gt;) to achieve &lt;em&gt;load_balance&lt;/em&gt; or &lt;em&gt;failover&lt;/em&gt; from one sink to another, with the help of &lt;em&gt;sink processor&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;my_agent.sinkgroups=g12a
my_agent.sinkgroups.g12a.sinks = k12a k12b k12c k12d k12e k12f k12g k12h
my_agent.sinkgroups.g12a.processor.type = load_balance
my_agent.sinkgroups.g12a.processor.backoff = true
my_agent.sinkgroups.g12a.processor.selector = round_robin
my_agent.sinkgroups.g12a.processor.selector.maxTimeOut = 3000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If &lt;em&gt;backoff&lt;/em&gt; is enabled, the sink processor will backlist sinks that fail, removing them for a given timeout. When the timeout ends, if the sink is still unresponsive, the timeout is increased exponentionally.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Each source and sink should be assigned to a channel.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;my_agent.sources.r12a.channels = c12
my_agent.sources.r12b.channels = c12
my_agent.sinks.k12a.channel = c12
my_agent.sinks.k12b.channel = c12
my_agent.sinks.k12c.channel = c12
my_agent.sinks.k12d.channel = c12
my_agent.sinks.k12e.channel = c12
my_agent.sinks.k12f.channel = c12
my_agent.sinks.k12g.channel = c12
my_agent.sinks.k12h.channel = c12
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;starting-an-agent&quot;&gt;Starting an Agent&lt;/h1&gt;

&lt;p&gt;Flume distribution brings in a shell script under its bin directory: &lt;em&gt;flume-ng&lt;/em&gt;. We should specify the agent name defined in configuration file.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# bin/flume-ng --help&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# bin/flume-ng agent -c conf -f conf/flume-conf.properties -n $agent_name &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Elastic Stack</title>
   <link href="/2019/04/10/elastic-stack/"/>
   <updated>2019-04-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/04/10/elastic-stack</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#top-down-architecture&quot; id=&quot;markdown-toc-top-down-architecture&quot;&gt;Top-down Architecture&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#reference&quot; id=&quot;markdown-toc-reference&quot;&gt;Reference&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#prerequisites&quot; id=&quot;markdown-toc-prerequisites&quot;&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#repo&quot; id=&quot;markdown-toc-repo&quot;&gt;Repo&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#logstash&quot; id=&quot;markdown-toc-logstash&quot;&gt;Logstash&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#filebeat&quot; id=&quot;markdown-toc-filebeat&quot;&gt;Filebeat&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#install-filebeat&quot; id=&quot;markdown-toc-install-filebeat&quot;&gt;Install Filebeat&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#beats-yaml&quot; id=&quot;markdown-toc-beats-yaml&quot;&gt;Beats YAML&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#filebeat-configuration&quot; id=&quot;markdown-toc-filebeat-configuration&quot;&gt;Filebeat Configuration&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#filebeat-pre-start&quot; id=&quot;markdown-toc-filebeat-pre-start&quot;&gt;Filebeat Pre-start&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#start-filebeat&quot; id=&quot;markdown-toc-start-filebeat&quot;&gt;Start Filebeat&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#stop-filebeat&quot; id=&quot;markdown-toc-stop-filebeat&quot;&gt;Stop Filebeat&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#filebeat-processors&quot; id=&quot;markdown-toc-filebeat-processors&quot;&gt;Filebeat Processors&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#decode-json&quot; id=&quot;markdown-toc-decode-json&quot;&gt;Decode Json&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;top-down-architecture&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started.html&quot;&gt;Top-down Architecture&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;Elastic Stack is called ELK previously. Due new products like Beats and X-Pack, the acronym is changed accordingly.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/elastic-stack.png&quot; alt=&quot;elastic-stack&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Kibana&lt;/p&gt;

    &lt;p&gt;The frontend of the stack: search and virtualize data like charts and tables.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Elasticsearch&lt;/p&gt;

    &lt;p&gt;Jason-based search engine (based on Lucene): index, analyze and store data as Json format.&lt;/p&gt;

    &lt;p&gt;From the figure above, we know that Elasticsearch is the heart of the stack. We will find below that the Elastic Stack repository (for CentOS) is called &lt;em&gt;elasticsearch&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Logstash&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;stash [vt] to store in a usually secret place for future use&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Data collection pipeline: unify and normalize data. The name comprises &apos;log&apos; and &apos;stash&apos;. &apos;log&apos; means the &lt;em&gt;input&lt;/em&gt; (source data) while &apos;stash&apos; means &lt;em&gt;output&lt;/em&gt; (store the data). Between the input and output, there is the optional &lt;em&gt;filter&lt;/em&gt; component. Logstash has now evolved into a more general tool. It can even receive data from and/or send data to Kafka (another FOSS project).&lt;/p&gt;

    &lt;p&gt;Logstash will format the data in Json format and send out to Elasticsearch (the stash).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Beats&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;beat [c] A stroke or blow. In music, a beat is a unit of measurement.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Agent: ships different types of data from edge devices to Logstash or directly to Elasticsearch.&lt;/p&gt;

    &lt;p&gt;There are different kinds of beats desginated for different kinds of data. For example, Filebeat is to collect log files (i.e. &lt;em&gt;access.log&lt;/em&gt; and &lt;em&gt;error.log&lt;/em&gt;) with modules. A Nginx module collects Nginx log files; a MySQL module collects MySQL log files. Another beat is Metricbeat that collects system-level and/or service-level performance metrics like CPU and memory usage for the operating system. It also ships with modules for popular services such as Nginx, MySQL etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Elastic Stack Features&lt;/p&gt;

    &lt;p&gt;Formerly known as X-Pack - addons: a pack of extensions to the stack, like authentication, monitoring &amp;amp; altering, reporting, Elasticsearch SQL, and machine learning (abnormality detection, forecasting, relation graph).&lt;/p&gt;

    &lt;p&gt;For relation graph, pay attention to the difference between &lt;em&gt;relevance&lt;/em&gt; and &lt;em&gt;popularity&lt;/em&gt;. Mostly, relevance is what we desire. All colleagues use Google search in a team does not mean they are relevant as per Google: it is just becuase Google is popular.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/elastic-stack/current/installing-elastic-stack.html&quot;&gt;Installation&lt;/a&gt;&lt;/h1&gt;

&lt;h2 id=&quot;reference&quot;&gt;Reference&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://juejin.im/post/5c78af896fb9a049fc043847&quot;&gt;juejin.im&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cnblogs.com/flying607/p/9403199.html&quot;&gt;cnblogs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-install-elasticsearch-logstash-and-kibana-elastic-stack-on-centos-7&quot;&gt;digitalocean&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.howtoforge.com/tutorial/how-to-install-elastic-stack-on-centos-7/&quot;&gt;howtoforge&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Java 8&lt;/li&gt;
  &lt;li&gt;Use the same version across the entire stack.&lt;/li&gt;
  &lt;li&gt;Follow the order: Elasticsearch, Kibana, Logstash, Beats etc.&lt;/li&gt;
  &lt;li&gt;Each component can be installed by justing extracting tarballs or through official &apos;yum&apos; repository.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;repo&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/7.0/setup-repositories.html&quot;&gt;Repo&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Import key:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rpmkeys &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; https://packages.elastic.co/GPG-KEY-elasticsearch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add the repository:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/pki/rpm-gpg/elastic-stack.repo &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;
&amp;gt; [elastic-7.x]
&amp;gt; name=Elastic repository for 7.x packages
&amp;gt; baseurl=https://artifacts.elastic.co/packages/7.x/yum
&amp;gt; gpgcheck=1
&amp;gt; gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
&amp;gt; enabled=1
&amp;gt; autorefresh=1
&amp;gt; type=rpm-md
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Search for a package:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;yum search elasticsearch kibana
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;logstash&quot;&gt;Logstash&lt;/h1&gt;

&lt;p&gt;Congfiguration file format is writen in a format similar to Json.&lt;/p&gt;

&lt;h1 id=&quot;filebeat&quot;&gt;Filebeat&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Filebeat support various outputs but we usually just send the events directly to Elasticsearch or to Logstash for additional processing. Events can also be sent to products out of the Elastic Stack like Kafka.&lt;/li&gt;
  &lt;li&gt;Filebeat uses &lt;em&gt;backpressure-sensative&lt;/em&gt; protocol to do congestion control, adjusting the speed of reading log entries in accord with Logstash or Elasticsearch staus.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&apos;inputs&apos; generate &apos;event&apos;s in Json format; &apos;processors&apos; filters events; &apos;output&apos; ships events out.&lt;/p&gt;

    &lt;p&gt;&apos;field&apos; refers to the key part of an event &apos;key: value&apos; pair.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;install-filebeat&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/7.0/directory-layout.html&quot;&gt;Install Filebeat&lt;/a&gt;&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;yum search filebeat
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;filebeat
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-ql&lt;/span&gt; filebeat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The package includes a &lt;em&gt;sysvinit&lt;/em&gt; script, namely &lt;em&gt;/etc/init.d/filebeat&lt;/em&gt;. In the &apos;Filebeat Start&apos; section, we will discuss how to utlize this script for Sytemd startup.&lt;/p&gt;

&lt;h2 id=&quot;beats-yaml&quot;&gt;Beats &lt;a href=&quot;https://www.elastic.co/guide/en/beats/libbeat/7.0/config-file-format.html&quot;&gt;YAML&lt;/a&gt;&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;This applies to all beats applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Configuration is writen in YAML format, demanding &lt;em&gt;strict indentation&lt;/em&gt;. All settings are structured using dictionaries and lists. Please use the same number of spaces and avoid tabs for dictionary pairs and list items. The structured form collapses to a &lt;a href=&quot;https://www.elastic.co/guide/en/beats/libbeat/7.0/config-file-format-namespacing.html&quot;&gt;namespaced&lt;/a&gt; naming method.&lt;/p&gt;

&lt;p&gt;Dictionary is represented with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key: value&lt;/code&gt; pairs in the same indentation level, with the &apos;:&apos; separator followed by a space or newline. Multiple pairs can be put on the same line in an abbreviated form:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Enclosed by braces
person: {name: &quot;John Doe&quot;, age: 34, country: &quot;Canada&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A list item takes the form: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;- &lt;/code&gt;, namely a dash followed by a space. All list items of a list should be at the same indetation level. In the following example, &apos;colors&apos; is a dictionary &apos;key&apos; with the value part a list consisted of three items.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;colors&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Red&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Green&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Blue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Multiple list items can also be abbreviated as:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Enclosed by square brackets&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;colors&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Red&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Green&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Blue&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Whenever a semicolon appears followed by a space, it is a dictionary pair. Whenever a dash followed by a space, it is a list item.&lt;/p&gt;

&lt;p&gt;Configuration Notice:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Please use single quotes for regex and pathnames that containing spaces or special characters.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;System environment variables and configuration variables (defined within YML itself) are referenced in the form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${VAR:default-value}&lt;/code&gt;. Environment variables are expanded before YAML parsing. So we CANNOT refer to system environment variables within YAML files of &apos;Live Reloading&apos; as those files are reloaded periodically but after the main YAML parsing.&lt;/p&gt;

    &lt;p&gt;The &lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/current/command-line-options.html&quot;&gt;command line&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-E&lt;/code&gt; option can be used to override variables like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-E key=value&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Aside environment and configuration variable reference, event field can be referenced in the form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%{[field-name]:default-value}&lt;/code&gt;. Pay attention please, the prefix symbol is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt;. Event fields are accessed using field references &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[field-name]&lt;/code&gt;. This is called &lt;a href=&quot;https://www.elastic.co/guide/en/beats/libbeat/current/config-file-format-type.html&quot;&gt;Format String (sprintf)&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;filebeat-configuration&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/master/configuring-howto-filebeat.html&quot;&gt;Filebeat Configuration&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;By default, configuration files are installed to &lt;em&gt;/etc/filebeat&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ll /etc/filebeat/

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; total 300
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt; 1 root root 219620 Apr  5 22:11 fields.yml
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rw-r--r--&lt;/span&gt; 1 root root  71973 Apr  5 22:11 filebeat.reference.yml
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rw-------&lt;/span&gt; 1 root root   7745 Apr  5 22:11 filebeat.yml
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; drwxr-xr-x 2 root root   4096 Apr 18 08:06 modules.d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All configuration files are writen in YAML format. For pre-defined fields, check the installed &apos;fields.yml&apos;. &apos;filebeat.reference.yml&apos; is the reference sample. &apos;filebeat.yml&apos; is the default configuration. &apos;modules.d&apos; contains built-in configurations for modules like Nginx, Apache etc. Filebeat supports &lt;a href=&quot;https://golang.org/pkg/path/filepath/#Glob&quot;&gt;Golang glob&lt;/a&gt; syntax. Especially, &lt;a href=&quot;https://unix.stackexchange.com/a/117828&quot;&gt;globstar&lt;/a&gt; can be enabled by directive &apos;recursive_glob.enabled&apos; (default to &apos;true&apos;).&lt;/p&gt;

&lt;p&gt;The following are hands-on configuration practice:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Paths&lt;/p&gt;

    &lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# default to the location of the Filebeat binary&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;path.home&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/opt/filebeat&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# configuration location&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;path.config&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${path.home}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# data location&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;path.data&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${path.home}/data&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Agent logs&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;path.logs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${path.home}/logs&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# By yum repo&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;path.home&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/usr/share/filebeat&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;path.config&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/etc/filebeat&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;path.data&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/var/lib/filebeat&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;path.logs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/var/log/filebeat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&apos;path.home&apos; is usually set to the installation location.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/current/configuration-general-options.htm&quot;&gt;Global and General options&lt;/a&gt;&lt;/p&gt;

    &lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Filebeat&apos;s global options&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;filebeat.registry.path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${path.data}/registry&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# General options that are supported by all Elastic beats&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;filebeat-log-project&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;project-X&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;nginx&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;fields_under_root&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;X&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;instance-id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;574734885120952459&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The &lt;em&gt;registry&lt;/em&gt; file stores the state and location information that Filebeat uses to track where it was last reading. If a relative path is passed, it is considered relative to the data path. It defaults to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${path.data}/registry&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;The general &apos;fields_under_root&apos; field applies to field &apos;fields&apos; that is added to the event.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Logging&lt;/p&gt;

    &lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;logging.level&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;info&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#logging.selectors: [&quot;*&quot;]&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;logging.to_files&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;logging.to_syslog&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;logging.json&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;logging.files&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;${path.home}/logs&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;filebeat.log&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;rotateeverybytes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10485760&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;keepfiles&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;7&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;permissions&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0644&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Log settings for the Filebeat agent itself. If the &apos;path&apos; is a relative pathname, it would be relative to the &apos;path.home&apos;.&lt;/li&gt;
      &lt;li&gt;Log options can be modified on command line directly. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d &apos;*&apos;&lt;/code&gt; enables &lt;em&gt;debug&lt;/em&gt; level for all components.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;HTTP Server&lt;/p&gt;

    &lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;http.enabled&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;http.host&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;localhost&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;http.port&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5066&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Filebeat has a built-in HTTP server, exposing internal metrics.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl http://localhost:5066/?pretty
~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl http://localhost:5066/stats?pretty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/current/_live_reloading.html&quot;&gt;Live Reloading&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Like many other services, Filebeat can load configurations from external files. In &apos;filebeat.yml&apos;, we can set values of key &apos;filebeat.inputs&apos; and key &apos;filebeat.modules&apos; from extra YAML files.&lt;/p&gt;

    &lt;p&gt;For inputs:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;filebeat.config.inputs:
  enabled: true
  path: inputs.d/*.yml
  reload.enabled: true
  reload.period: 10s     
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Each file matched by the &apos;path&apos; glob must contain a list of one or more inputs.&lt;/p&gt;

    &lt;p&gt;For modules:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;filebeat.config.modules:
  enabled: true
  path: ${path.config}/modules.d/*.yml
  reload.enabled: true
  reload.period: 10s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If the subcommand &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filebeat modules&lt;/code&gt; is used to disable or enable modules, then &apos;path&apos; &lt;strong&gt;MUST&lt;/strong&gt; point to a location called &lt;em&gt;modules.d&lt;/em&gt;. Similarly, each matched globbing must contain a list of one or more module definitions (i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;- module: nginx&lt;/code&gt;).&lt;/p&gt;

    &lt;p&gt;However, live reloading is limited sometimes. For example, if a system environment variable is modified or defined, the process wound not know about it unless restarted.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Modules and Inputs&lt;/p&gt;

    &lt;p&gt;Filebeat reads logs from either &apos;filebeat.inputs&apos; or &apos;filebeat.modules&apos;. &apos;filebeat.inputs&apos; is mainly used to read arbitrary log files while modules read common service logs with predefined settings that is quite handy.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;filebeat.modules:
  - module: nginx
    access:
      enabled: true
      var.paths: /var/log/nginx/access.log
    error:
      enabled: true
      var.paths: /var/log/nginx/error.log

filebeat.inputs:
  - type: log
    enabled: true
    paths:
  - /var/log/myJson.log
    scan_frequency: 10s
    exclude_files: [&apos;.gz$&apos;,&apos;~$&apos;]

    fields_under_root: true
    fields:
      hostname: &quot;${HOSTNAME:-}&quot;

    json.keys_under_root: true
    json.overwrite_keys: false

    json.message_key: &quot;hostHeader&quot;
    include_lines: [&apos;www.bing.com&apos;,&apos;www.example.com&apos;]
    exclude_lines: [&apos;a-shit-hostHeader&apos;,&apos;b-shit-HostHeader&apos;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&apos;paths&apos; must be &lt;strong&gt;unique&lt;/strong&gt; among multiple inputs. If more than one inputs harvests the same file, it would lead to unexpected behavior.&lt;/li&gt;
      &lt;li&gt;Only log entries whose &apos;hostHeader&apos; value matching &apos;include_lines&apos; will be harvested.&lt;/li&gt;
      &lt;li&gt;&apos;include_lines&apos; is applied before &apos;exclude_lines&apos; regardless of the order they appear.&lt;/li&gt;
      &lt;li&gt;Read more about &lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/7.0/configuration-filebeat-modules.html&quot;&gt;modules configuration&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Processors&lt;/p&gt;

    &lt;p&gt;Processor is probably one of the most important &lt;em&gt;general&lt;/em&gt; option. A processor filters input logs by adding/dropping/modifying fields and/or events. It resembles &apos;exlude_files&apos;, &apos;include_lines&apos; and &apos;exclude_lines&apos; which are applied upon inputs. Processors, on the other hand, applies to fields/events after inputs and before put to outputs.&lt;/p&gt;

    &lt;p&gt;An event can go through a chain of processors in &lt;em&gt;the exact order&lt;/em&gt; they are defined, before sending out.&lt;/p&gt;

    &lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;processors&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;include_fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;cpu&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;drop_fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@timestamp&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@metadata&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;log&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tags&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;input&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ecs&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;host&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;agent&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;message&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;drop_event&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;http.code&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;200&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;decode_json_fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;message&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;process_array&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;max_depth&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;overwrite_keys&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;More about processors, please check the &apos;Filebeat Processors&apos; section below.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Outputs&lt;/p&gt;

    &lt;p&gt;Here is an excerpt of outputing &lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/7.0/kafka-output.html&quot;&gt;to Kafka&lt;/a&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;output.kafka:
  enabled: true
  hosts: [&quot;logger1:9092&quot;, &quot;logger2:9092&quot;, &quot;logger3:9092&quot;] # initial broker seeds to retrieve metadata of Kafka and Zookeeper

  topic: &quot;cdn-sre&quot;
  #topics:

  partition.round_robin:
    reachable_only: true
    group_events: 3
  version: &apos;2.0.0&apos;
  codec.json:
    pretty: false
    escape_html: false
  worker: 3
  compression: gzip
  required_acks: 1
  max_message_bytes: 1000000
  client_id: ${HOSTNAME:localhost}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;The &apos;hosts&apos; provides only the initial list of Kafka &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listeners&lt;/code&gt; from which to fetch the whole cluster metadata, including the full list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;advertised.listeners&lt;/code&gt; where events are published to.&lt;/li&gt;
      &lt;li&gt;Besides the &apos;topic&apos; directive, there is also a &apos;topics&apos; sub-directive that filters events and publish them to different Kafka topics. It is a useful feature is not constrained by the &lt;em&gt;one and only one&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;output&lt;/code&gt; rule. That is to say, &apos;output.kafka&apos; can publish events to multiple topics.&lt;/li&gt;
      &lt;li&gt;&apos;group_events&apos; and &apos;worker&apos; can be set the same value.&lt;/li&gt;
      &lt;li&gt;&apos;max_message_bytes&apos; should be equal to or less than the Kafka broker&apos;s &apos;message.max.bytes&apos;&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Like the console consumer/producer of Kafka, Filebeat can output events into console and/or files.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;output.file:
  enabled: true
  codec.json:
    pretty: true
    escape_html: false
  path: ${path.logs}
  filename: filebeat.out
  rotate_every_kb: 10000
  number_of_files: 7

output.console:
  enabled: true
  codec.json:
    pretty: true
    escape_html: false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Beats support one and only one &lt;em&gt;output&lt;/em&gt;. If you desire multiple outputs, then send to Logstash or Kafka first.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;filebeat-pre-start&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/7.0/setting-up-and-running.html&quot;&gt;Filebeat Pre-start&lt;/a&gt;&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;This applies to all beats applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On POSIX systems, configuration files are subject to &lt;a href=&quot;https://www.elastic.co/guide/en/beats/libbeat/7.0/config-file-permissions.html&quot;&gt;ownership and permission checks&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The owner of configuration files must be the user that is running the beat applications or the &lt;em&gt;root&lt;/em&gt; account.&lt;/li&gt;
  &lt;li&gt;The permissions of configuration files permit &apos;write&apos; only by the owner itself which can be 0644 or 0600.&lt;/li&gt;
  &lt;li&gt;The permission and owner checks can be disabled temperarily on command line by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--strict.perms=false&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Filebeat supports a set of commands like &lt;em&gt;help&lt;/em&gt;, &lt;em&gt;test&lt;/em&gt;, &lt;em&gt;export&lt;/em&gt;, &lt;em&gt;modules&lt;/em&gt; etc. We can use &lt;em&gt;test&lt;/em&gt; to check configuration syntax:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;beatname &lt;span class=&quot;nb&quot;&gt;help test
&lt;/span&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;beatname &lt;span class=&quot;nb&quot;&gt;test &lt;/span&gt;config &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; /path/to/beatname1.yml

&lt;span class=&quot;c&quot;&gt;# verify if Filebeat can connect the outputs:&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;beatname &lt;span class=&quot;nb&quot;&gt;test &lt;/span&gt;output &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; /path/to/beatname1.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, all built-in modules are disabled, the &lt;em&gt;module&lt;/em&gt; command can manage modules on the fly, similar to the mechanism of &apos;filebeat.config.inputs&apos;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;filebeat modules list
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;filebeat modules &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;nginx
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;filebeat modules disable nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Command &lt;em&gt;export&lt;/em&gt; exports current config to STDOUT without comments:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;filebeat &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;start-filebeat&quot;&gt;Start Filebeat&lt;/h2&gt;

&lt;p&gt;Firstly enable Filebeat on boot:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;chkconfig &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; filebeat
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;chkconfig &lt;span class=&quot;nt&quot;&gt;--list&lt;/span&gt; filebeat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;chkconfig&lt;/em&gt; creates corresponding symlinks under &lt;em&gt;/etc/rc.x/&lt;/em&gt; according to the &lt;a href=&quot;https://fedoraproject.org/wiki/EPEL:SysVInitScripts#Chkconfig_Header&quot;&gt;Chkconfig Header&lt;/a&gt;. &lt;em&gt;/usr/lib/systemd/system-generators/systemd-sysv-generator&lt;/em&gt; of Systemd will then auto-create the unit file according to &lt;a href=&quot;https://fedoraproject.org/wiki/EPEL:SysVInitScripts#LSB_Header&quot;&gt;LSB Header&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Start Filebeat:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;service filebeat status
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;service filebeat start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We cannot provide &lt;em&gt;filebeat&lt;/em&gt; options and arguments by &lt;em&gt;/etc/init.d/filebeat&lt;/em&gt; script. Alternatively, we can manually start the service:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# run in foreground with &apos;-e&apos; option&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; /usr/bin/filebeat &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; /etc/filebeat/filebeat.yml &lt;span class=&quot;nt&quot;&gt;-path&lt;/span&gt;.home /usr/share/filebeat &lt;span class=&quot;nt&quot;&gt;-path&lt;/span&gt;.config /etc/filebeat &lt;span class=&quot;nt&quot;&gt;-path&lt;/span&gt;.data /var/lib/filebeat &lt;span class=&quot;nt&quot;&gt;-path&lt;/span&gt;.logs /var/log/filebeat/
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; /path/to/filebeat &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; /path/to/filebeat.yml

&lt;span class=&quot;c&quot;&gt;# run in background; enable &apos;NOPASSWD:&apos; or use &apos;-b&apos; option&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nohup sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; ./filebeat &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; apple/filebeat.yml &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; logs/nohup.out 2&amp;gt;&amp;amp;1 &amp;amp;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nohup&lt;/span&gt; ./filebeat &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; apple/filebeat.yml &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; logs/nohup.out 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The order of &apos;sudo&apos; and &apos;nohup&apos; &lt;a href=&quot;https://unix.stackexchange.com/q/413096&quot;&gt;does not matter&lt;/a&gt; in terms of &apos;SIGHUP&apos;&lt;/p&gt;

    &lt;p&gt;But it makes a difference which part the &apos;sudo&apos; is applied to.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e&lt;/code&gt; option is useful for debugging in that it logs to STDERR and disables syslog/file output.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;stop-filebeat&quot;&gt;Stop Filebeat&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;If Filebeat is launched as a system service, stop it via the system service management functionality.&lt;/li&gt;
  &lt;li&gt;If Filebeat is invoked in the console, stop it by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-c&lt;/code&gt; or &apos;SIGTERM&apos; signal.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;filebeat-processors&quot;&gt;&lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/master/filtering-and-enhancing-data.html&quot;&gt;Filebeat Processors&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;libbeat&lt;/em&gt; library provides processors for:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;reducing the number of exported &lt;em&gt;field&lt;/em&gt;s;&lt;/li&gt;
  &lt;li&gt;enhancing events with additional metadata;&lt;/li&gt;
  &lt;li&gt;performing additional processing and decoding.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, to drop messages beginning with &apos;DBG:&apos;:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;processors&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;drop_event&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;regex&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;^DBG:&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A processor consists of a name, an optional &lt;em&gt;when&lt;/em&gt; condition and a set of parameters:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;processors&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;&amp;lt;processor_name&amp;gt;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;&amp;lt;condition&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;lt;parameters&amp;gt;&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;&amp;lt;processor_name&amp;gt;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;&amp;lt;condition&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;lt;parameters&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&apos;processor_name&apos; is a one of the pre-defined processor name.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;when&lt;/em&gt; is a filter condition.&lt;/li&gt;
  &lt;li&gt;&apos;when&apos; and &apos;parameters&apos; &lt;strong&gt;must&lt;/strong&gt; be defined &lt;a href=&quot;https://discuss.elastic.co/t/error-initializing-processors/99247/8&quot;&gt;under the namespace&lt;/a&gt; of &apos;processor_name&apos; which is a list item. The abbreviated form is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;- &amp;lt;processor_name&amp;gt;: {when: {&amp;lt;condition&amp;gt;},&amp;lt;parameters&amp;gt;}&lt;/code&gt;. Consequently, they are indented further compared with &apos;processor_name&apos;.
    &lt;ol&gt;
      &lt;li&gt;It a list item.&lt;/li&gt;
      &lt;li&gt;The item value is a dictionary &apos;key: value&apos; pair.&lt;/li&gt;
      &lt;li&gt;The value of the pair comprises lists and dictionaries.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Processors are applied in the order they are defined and are valid at different levels:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;At the top-level (root level) in &apos;filebeat.yml&apos; for all collected events;&lt;/li&gt;
  &lt;li&gt;Under a specific input applied only to that particular input. When to drop universal fields (i.e. &apos;agent&apos; and &apos;ecs&apos;), &apos;drop_fields&apos; should be defined in the top level.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;decode-json&quot;&gt;Decode Json&lt;/h3&gt;

&lt;p&gt;If a log entry is in Json format, Filebeat will escape the Json object like this:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;outer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;inner&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;{&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;}&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From the sample outpout, the field &apos;inner&apos; has a Json object escaped. To decode a Json field, means removing the escaping behaviour.&lt;/p&gt;

&lt;p&gt;Here is a hands-on schema on how to correctly decode collected Json logs under the field of &apos;message&apos;:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;log&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;exclude_files&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.gz$&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;~$&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;na&quot;&gt;json.keys_under_root&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;json.overwrite_keys&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;json.message_key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;host&quot;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# apply line and multiline filtering in accord with the specified Json key&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;include_lines&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;www.example.com&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;exclude_lines&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;shit&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;processors&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;decode_json_fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;message&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;process_array&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;max_depth&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;overwrite_keys&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;drop_fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@timestamp&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@metadata&apos;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;log&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;tags&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;input&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ecs&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;host&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;agent&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;message&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Json Decoding can be configured at either &apos;inputs&apos; level or &apos;processors&apos; level.&lt;/li&gt;
  &lt;li&gt;Regarding per-input level, as long as any one of the &apos;json.keys_under_root&apos;, &apos;json.overwrite_keys&apos; and &apos;json.message_key&apos; directives appear, Json decoding is applied.
    &lt;ol&gt;
      &lt;li&gt;&apos;json.keys_under_root&apos; places the decode Json at the root level.&lt;/li&gt;
      &lt;li&gt;Decoded &apos;key: value&apos; pairs will overwrite built-in pairs that share the same key if &apos;json.overwrite_keys&apos; is enabled.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Json decoding happens &lt;strong&gt;before&lt;/strong&gt; line (i.e. &apos;exclude_lines&apos;) filtering and &lt;a href=&quot;https://www.elastic.co/guide/en/beats/filebeat/current/multiline-examples.html&quot;&gt;multiline filtering&lt;/a&gt;. Hence, line and multiline filtering does not affect the original Json event as it is transformed.&lt;/p&gt;

        &lt;p&gt;The &apos;json.message_key&apos; specifies a decoded Json key and applies line and multiline filtering to the event according the key value.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&apos;decode_json_fields&apos; is a global processor that applies to all inputs, with the &apos;fields&apos; directive pointing to event fileds that require Json decoding.
    &lt;ol&gt;
      &lt;li&gt;&apos;target: &quot;&quot;&apos; is equivalent to &apos;json.keys_under_root&apos;.&lt;/li&gt;
      &lt;li&gt;&apos;overwrite_keys&apos; and &apos;json.overwrite_keys&apos; are equivalent as well.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&apos;@metadata&apos; and &apos;@timestamp&apos; cannot be dropped even they appear in in the list. Filebeat requires &apos;@metadata&apos; when sending out events (i.e. to Logstash).&lt;/p&gt;

    &lt;p&gt;A particular setup flow is like &apos;Filebeat - Kafka - Logstash&apos;. We filter out the two fields in Logstash.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;: Filebeat refuses to launch on some systems when either &apos;overwrite_keys&apos; or &apos;json.overwrite_keys&apos; is enabled. Check &lt;a href=&quot;https://github.com/elastic/beats/issues/6381&quot;&gt;issue 6381&lt;/a&gt; and &lt;a href=&quot;https://github.com/elastic/beats/issues/1378&quot;&gt;issue 1378&lt;/a&gt;. Therefore, it is recommended to leave those two directives disabled.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Gitlab Jenkins</title>
   <link href="/2019/04/03/gitlab-jenkins/"/>
   <updated>2019-04-03T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/04/03/gitlab-jenkins</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#abcs&quot; id=&quot;markdown-toc-abcs&quot;&gt;ABCs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#qa&quot; id=&quot;markdown-toc-qa&quot;&gt;QA&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Jenkins is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Continuous_integration&quot;&gt;Continuous Integration (CI) &lt;/a&gt; utility. Among others, which is mostly used to &lt;em&gt;automate&lt;/em&gt; building, testing, delivering or deploying packages upon sources pushed to the mainlin repository.&lt;/li&gt;
  &lt;li&gt;Gitlab requires &lt;a href=&quot;https://docs.gitlab.com/ee/user/project/integrations/webhooks.html&quot;&gt;Webhooks&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Jenkins requires &lt;a href=&quot;https://github.com/jenkinsci/gitlab-plugin&quot;&gt;gitlab-plugin&lt;/a&gt; or &lt;a href=&quot;https://wiki.jenkins.io/display/JENKINS/Gitlab+Hook+Plugin&quot;&gt;Gitlab Webhook Plugin&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Generally speaking, the Webhook defined in Gitlag repository will call the Gitlab Webhook Plugin associated with Jenkins server which in return performs the build.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Read &lt;a href=&quot;https://medium.com/@teeks99/continuous-integration-with-jenkins-and-gitlab-fa770c62e88a&quot;&gt;Continuous Integration with Jenkins and GitLab&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;installation&quot;&gt;&lt;a href=&quot;https://wiki.jenkins.io/display/JENKINS/Installing+Jenkins+on+Red+Hat+distributions&quot;&gt;Installation&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Choose the &lt;a href=&quot;https://jenkins.io/changelog-stable/&quot;&gt;Long-term Support (LTS)&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Java is located under &apos;/home/shibin.luo/collectflume/jdk1.8.0_112/bin/java&apos;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Yum&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# sudo rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# sudo yum install jenkins&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;https://medium.com/@teeks99/continuous-integration-with-jenkins-and-gitlab-fa770c62e88a&lt;/p&gt;

&lt;h1 id=&quot;qa&quot;&gt;QA&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;ccssh5 &lt;a href=&quot;http://59.42.253.31:8080&quot;&gt;BGP-GZ-b-3gb&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Build status &lt;a href=&quot;https://github.com/jenkinsci/gitlab-plugin&quot;&gt;feedback&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Jenkins master/slave.&lt;/li&gt;
  &lt;li&gt;Java&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>rxvt-unicode</title>
   <link href="/2019/03/12/urxvt/"/>
   <updated>2019-03-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/03/12/urxvt</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#daemon-mode&quot; id=&quot;markdown-toc-daemon-mode&quot;&gt;Daemon Mode&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configuration&quot; id=&quot;markdown-toc-configuration&quot;&gt;Configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@host ~ #] pacman -S rxvt-unicode

[root@host ~ #] echo &apos;x11-terms/rxvt-unicode xft perl 256-color&apos; &amp;gt;&amp;gt; /etc/portage/package.use/urxvt
# Add to &apos;/etc/portage/patches/x11-terms/rxvt-unicode-9.21/&apos; the patch &apos;secondary-wheel.patch&apos;
[root@host ~ #] emerge -avt x11-terms/rxvt-unicode
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;daemon-mode&quot;&gt;Daemon Mode&lt;/h1&gt;

&lt;p&gt;Like Emacs, daemon mode speeds up startup speed.&lt;/p&gt;

&lt;p&gt;Put the following code line into auto-start script or X setting.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;urxvtd --quiet --opendisplay --fork
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To launch client side, just &lt;em&gt;urxvtc&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If the daemon is terminated, all running clients would be terminated as well.&lt;/li&gt;
  &lt;li&gt;By default, the local listening socket is located at &lt;em&gt;~/.urxvt/urxvtd-hostname&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;/h1&gt;

&lt;p&gt;Add to &lt;em&gt;~/.Xresources&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#include &quot;.Xresources.d/urxvt&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then customize options there. To configure &lt;a href=&quot;http://github.com/solarized/xresources&quot;&gt;Solarized&lt;/a&gt; color theme, clone the resources, the include the pathname.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# .Xresources.d/urxvt

#include &quot;Xresources.dark&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>X</title>
   <link href="/2019/03/11/x/"/>
   <updated>2019-03-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2019/03/11/x</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#x&quot; id=&quot;markdown-toc-x&quot;&gt;X&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#xorg&quot; id=&quot;markdown-toc-xorg&quot;&gt;Xorg&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#video-driver&quot; id=&quot;markdown-toc-video-driver&quot;&gt;Video Driver&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#hardware-acceleration&quot; id=&quot;markdown-toc-hardware-acceleration&quot;&gt;Hardware Acceleration&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#kde&quot; id=&quot;markdown-toc-kde&quot;&gt;KDE&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#awesome---window-manager&quot; id=&quot;markdown-toc-awesome---window-manager&quot;&gt;Awesome - Window Manager&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#xinit&quot; id=&quot;markdown-toc-xinit&quot;&gt;Xinit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#xserverrc&quot; id=&quot;markdown-toc-xserverrc&quot;&gt;xserverrc&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#xinitrc&quot; id=&quot;markdown-toc-xinitrc&quot;&gt;xinitrc&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#automatic-startx-on-login&quot; id=&quot;markdown-toc-automatic-startx-on-login&quot;&gt;Automatic startx on login&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#touchpad&quot; id=&quot;markdown-toc-touchpad&quot;&gt;Touchpad&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#xkb&quot; id=&quot;markdown-toc-xkb&quot;&gt;XKB&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sysrq&quot; id=&quot;markdown-toc-sysrq&quot;&gt;SysRq&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;x&quot;&gt;X&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;X - window server
    &lt;ol&gt;
      &lt;li&gt;Xorg&lt;/li&gt;
      &lt;li&gt;Wayland&lt;/li&gt;
      &lt;li&gt;~/.Xdefaults. Deprecated but used by ancient applications like &lt;em&gt;urxvt&lt;/em&gt;. Now replaced by ~/.Xresources. X resources for applications in the form &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key: value&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;~/.Xmodmap. Deprecated by &lt;a href=&quot;#xkb&quot;&gt;XKB&lt;/a&gt; (either through &lt;em&gt;setxkbmap&lt;/em&gt; or directly in Xorg conf).&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Video Driver
    &lt;ol&gt;
      &lt;li&gt;Basic GPU driver&lt;/li&gt;
      &lt;li&gt;Hardware Acceleration&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Window Manager (WM) - manage GUI windows
    &lt;ol&gt;
      &lt;li&gt;Awesome&lt;/li&gt;
      &lt;li&gt;i3&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Display Manager (DM) - control graphical login and start WM/DE
    &lt;ol&gt;
      &lt;li&gt;SDDM&lt;/li&gt;
      &lt;li&gt;GDM&lt;/li&gt;
      &lt;li&gt;~/.xsessionrc. Config of DM (i.e. choose WM).&lt;/li&gt;
      &lt;li&gt;~/.xprofile. General config of X. Equivalent of &lt;em&gt;xinitrc&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;xinit/startx - manually start WM/DE
    &lt;ol&gt;
      &lt;li&gt;~/.xinitrc.
        &lt;ol&gt;
          &lt;li&gt;General config of X. Equivalent of &lt;em&gt;xprofile&lt;/em&gt;.&lt;/li&gt;
          &lt;li&gt;Set WM.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;~/.xserverrc. Start X server.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Desktop (DE) = WM + DM + more
    &lt;ol&gt;
      &lt;li&gt;Xfce&lt;/li&gt;
      &lt;li&gt;KDE Plasma&lt;/li&gt;
      &lt;li&gt;Gnome&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;xorg&quot;&gt;Xorg&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; xorg-server
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-al&lt;/span&gt; /usr/bin/X
/usr/bin/X: symboli &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;to /usr/bin/Xorg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;X is the generic name of X Window System display server. The binary X is a symbolic link to the real implementation - Xorg.&lt;/p&gt;

&lt;h1 id=&quot;video-driver&quot;&gt;Video Driver&lt;/h1&gt;

&lt;p&gt;Firstly, identify vedio cards:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@host ~]# lspci | grep -e VGA -e 3D
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The command returns:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Intel HD Graphics 520
NVIDIA GeForce 920M
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So the computer has an integrated Intel video card and a discrete NVIDIA video card respectivelly: it is called &lt;a href=&quot;https://wiki.archlinux.org/index.php/NVIDIA_Optimus&quot;&gt;NVIDIA Optimus&lt;/a&gt;. We have several choices to deal with NVIDIA Optimus: turn off one of the video card, use &lt;a href=&quot;https://wiki.archlinux.org/index.php/Bumblebee&quot;&gt;Bumbelee&lt;/a&gt;, use &lt;a href=&quot;https://wiki.archlinux.org/index.php/Nvidia-xrun&quot;&gt;Nvidia-xrun&lt;/a&gt; etc. Nvidia-xrun is recommended:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nvidia-xrun is a utility to allow Nvidia optimus enabled laptops run X server with discrete nvidia graphics on demand. This solution offers full GPU utilization, compatibility and better performance than Bumblebee.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If this Arch Linux is a VirtualBox guest, then install VirtualBox guest additions instead.&lt;/p&gt;

&lt;p&gt;Check &lt;a href=&quot;https://wiki.archlinux.org/index.php/xorg#Driver_installation&quot;&gt;Xorg video driver&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;hardware-acceleration&quot;&gt;Hardware Acceleration&lt;/h2&gt;

&lt;p&gt;There are &lt;a href=&quot;https://wiki.archlinux.org/index.php/Hardware_video_acceleration&quot;&gt;two libraries&lt;/a&gt; that support hardware acceleration, namely VA-API and VDPAU. Most applications use the VA-API but we can install both libraries.&lt;/p&gt;

&lt;p&gt;For applications that use the VA-API library:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; libva-mesa-driver
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vainfo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For applications that use the VDPAU library:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; mesa-vdpau
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vdpauinfo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Test:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mpv &lt;span class=&quot;nt&quot;&gt;--hwdec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;auto &amp;lt;video_filename&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;kde&quot;&gt;KDE&lt;/h1&gt;

&lt;p&gt;Currently, KDE sucks! This section only shows how to install KDE plasma.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; xorg-server
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;reboot

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; plasma-meta
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; sddm
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;sddm

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It seems that &lt;em&gt;sddm&lt;/em&gt; is quite slow to launch Plasma. We need to increase system &lt;em&gt;entropy&lt;/em&gt; by &lt;em&gt;haveged&lt;/em&gt; and/or &lt;em&gt;rng-tools&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; rng-tools
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;rngd
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl start rngd

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; haveged
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;haveged
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl start haveged
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It might relate to a &lt;a href=&quot;https://github.com/sddm/sddm/issues/1036#issuecomment-477633990&quot;&gt;kernel option unset&lt;/a&gt;. However, such hack uses &lt;em&gt;pseudo-random&lt;/em&gt; to increase entropy and may leave your system in risks.&lt;/p&gt;

&lt;h1 id=&quot;awesome---window-manager&quot;&gt;Awesome - Window Manager&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; awesome
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;user@host ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;awesome

&lt;span class=&quot;c&quot;&gt;# E: awesome: main:656: cannot open display (error 5)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;2018/06/10/awesome&quot;&gt;Awesome&lt;/a&gt; is just a Window Manager. We need Displayer Manager or xinit/startx to launch X server before Window Manager.&lt;/p&gt;

&lt;h1 id=&quot;xinit&quot;&gt;Xinit&lt;/h1&gt;

&lt;p&gt;We don&apos;t need a Display Manager.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; xorg-xinit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;startx&lt;/em&gt; is a wrapper script of &lt;em&gt;xinit&lt;/em&gt; that provides some basic settings:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /usr/bin/startx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;xserverrc&quot;&gt;xserverrc&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;xserverrc&lt;/em&gt; is the file to &lt;a href=&quot;https://wiki.archlinux.org/index.php/xorg#Rootless_Xorg&quot;&gt;start X server&lt;/a&gt;, sourced by &lt;em&gt;xinit&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# https://git.edevau.net/onkelbeh/GentooRepository/commit/9d68e491c96541f7cbf3d5766597906561bbf512&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;XDG_VTNR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tty&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/dev/tty1&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DISPLAY&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; /usr/bin/X &lt;span class=&quot;nt&quot;&gt;-nolisten&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-nolisten&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-keeptty&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; vt7
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;XDG_VTNR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eq&lt;/span&gt; 1 &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DISPLAY&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; /usr/bin/X &lt;span class=&quot;nt&quot;&gt;-nolisten&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-nolisten&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-keeptty&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; vt&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;XDG_VTNR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When using  a DM, the X server is running as &lt;em&gt;root&lt;/em&gt;. The X server log is located at &lt;em&gt;/var/log/Xorg.0.log&lt;/em&gt;. However, with &lt;em&gt;xinit&lt;/em&gt;, X server is run under normal account. The X server log is located at &lt;em&gt;~/.local/share/xorg/Xorg.0.log&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The last argument &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vtXY&lt;/code&gt; is the &lt;a href=&quot;2019/11/30/terminal-shell-sed/&quot;&gt;virtual terminal&lt;/a&gt; that Xorg will use. By default, X will use the one where it is started.&lt;/li&gt;
  &lt;li&gt;Xorg &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-keeptty&lt;/code&gt; will redirect log of &lt;em&gt;xinit&lt;/em&gt; iteself to &lt;em&gt;Xorg.0.log&lt;/em&gt; as well. Check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man Xserver&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man Xorg&lt;/code&gt; for more options.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;xinitrc&quot;&gt;xinitrc&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;~/.xinitrc&lt;/em&gt; defaults to &lt;em&gt;/etc/X11/xinit/xinitrc&lt;/em&gt;. This file is used to launch the DE/WM.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;user@host ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /path/to/xinitrc.bak ~/.xinitrc

&lt;span class=&quot;c&quot;&gt;# ~/.xinitrc&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#exec $command&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;awesome
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Commands after &lt;em&gt;exec&lt;/em&gt; won&apos;t be executed as it &lt;em&gt;replace&lt;/em&gt; the current shell. If any other commands are required, put them before &lt;em&gt;exec&lt;/em&gt; line.&lt;/p&gt;

&lt;p&gt;That is enough, just type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;startx&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;automatic-startx-on-login&quot;&gt;Automatic startx on login&lt;/h1&gt;

&lt;p&gt;Add the following code to &lt;em&gt;~/.bash_profile&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# auto startx&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;shopt&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; login_shell&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;XDG_VTNR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tty&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/dev/tty1&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DISPLAY&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;startx 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;tee&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;/.startx.log
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;XDG_VTNR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eq&lt;/span&gt; 1 &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DISPLAY&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;startx 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;tee&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;/.startx.log
  &lt;span class=&quot;k&quot;&gt;fi
fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We cal also append Xorg options to &lt;em&gt;startx&lt;/em&gt; directly like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;startx -- -keeptty&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;touchpad&quot;&gt;Touchpad&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;xorg-server&lt;/em&gt;, by default, depends on and uses &lt;a href=&quot;https://wiki.archlinux.org/index.php/Libinput#Configuration&quot;&gt;xf86-input-libinput&lt;/a&gt; for all input devices:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;user@tux ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fgrep &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Using input driver &quot;&lt;/span&gt; ~/.local/share/Xorg/Xorg.0.log
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;user@tux ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;libinput list-devices
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;user@tux ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;man 5 xorg.conf &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; man 4 libinput
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Before configuring Xorg, glimpse at &lt;em&gt;/usr/share/X11/xorg.conf.d&lt;/em&gt; and read the INPUTCLASS SECTION of &lt;em&gt;man 5 xorg.conf&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To configure Touchpad, we copy the skeleton from &lt;em&gt;40-libinput.conf&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@tux &lt;span class=&quot;c&quot;&gt;#]$ cp /usr/share/X11/xorg.conf.d/40-libinput.conf /etc/X11/xorg.conf.d/30-touchpad.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Identifier is any reasonable string specific to the device configured. I choose the exact device name from Xorg log.&lt;/li&gt;
  &lt;li&gt;Turn on &lt;em&gt;tap to click&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Two-finger click simulates &lt;em&gt;mouse middle buttion&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Three-finger click simulates &lt;em&gt;mouse right button&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;When mouse and touchpad events are detected simutaneously, ignore that of mouse.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Section &quot;InputClass&quot;
        Identifier &quot;DLL06F2:00 06CB:75DA Touchpad&quot;
        MatchDevicePath &quot;/dev/input/event*&quot;
        MatchIsTouchpad &quot;on&quot;
        Driver &quot;libinput&quot;
                Option &quot;Tapping&quot; &quot;on&quot;
                Option &quot;TappingButtonMap&quot; &quot;lmr&quot;
                Option &quot;ClickMethod&quot; &quot;clickfinger&quot;
                Option &quot;NaturalScrolling&quot; &quot;true&quot;
                Option &quot;ScrollMethod&quot; &quot;twofinger&quot;
EndSection

Section &quot;InputClass&quot;
        Identifier &quot;Touchpad ignore duplicates&quot;
        MatchDevicePath &quot;/dev/input/mouse*&quot;
        MatchIsTouchpad &quot;on&quot;
        MatchOS &quot;Linux&quot;
                Option &quot;Ignore&quot; &quot;on&quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;xkb&quot;&gt;XKB&lt;/h1&gt;

&lt;p&gt;Post &lt;a href=&quot;/2017/11/28/archlinux/#localization&quot;&gt;archlinux&lt;/a&gt; uses &lt;em&gt;/etc/vconsole.conf&lt;/em&gt; and/or &lt;em&gt;loadkeys&lt;/em&gt; to set keyboard layout for &lt;a href=&quot;/2019/11/30/terminal-shell-sed/&quot;&gt;virtual terminal&lt;/a&gt;. When it comes to X server, we utilize &lt;em&gt;XkbOptions&lt;/em&gt; of Xorg.conf or &lt;em&gt;setxkbmap&lt;/em&gt; in &lt;em&gt;.xinitrc&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Basically, I wanna &lt;a href=&quot;https://www.emacswiki.org/emacs/MovingTheCtrlKey&quot;&gt;switch&lt;/a&gt; &apos;Caps_Lock&apos; and &apos;Control_L&apos;, or even turn off &apos;Caps_Lock&apos;.&lt;/li&gt;
  &lt;li&gt;Check &lt;em&gt;/usr/share/X11/xkb/rules/base.lst&lt;/em&gt; for keyboard model (i.e. latitude) and layout (i.e. us).&lt;/li&gt;
  &lt;li&gt;Run the following command to see similar options:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[root@tux #]$ grep -E &quot;(ctrl|caps):&quot; /usr/share/X11/xkb/rules/base.lst
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By Xorg.conf:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/X11/xorg.conf.d/10-keyboard.conf

Section &quot;InputClass&quot;
        Identifier &quot;Keyboard switch Ctrl and CapsLk&quot;
        MatchIsKeyboard &quot;on&quot;
        Option &quot;XkbOptions&quot; &quot;ctrl:nocaps&quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By &lt;em&gt;setxkbmap&lt;/em&gt; (overrides settings in Xorg.conf) in &lt;em&gt;~/.xinitrc&lt;/em&gt; or &lt;em&gt;~/.xprofile&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;setxkbmap -model latitude -layout us -option ctrl:swapcaps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;sysrq&quot;&gt;SysRq&lt;/h1&gt;

&lt;p&gt;Check &lt;a href=&quot;/2015/03/25/gentoo-installation/&quot;&gt;Gentoo SysRq&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Emacs C/C++ IDE</title>
   <link href="/2018/12/03/emacs-cpp-ide/"/>
   <updated>2018-12-03T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/12/03/emacs-cpp-ide</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#tag&quot; id=&quot;markdown-toc-tag&quot;&gt;Tag&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#semantics-and-completion&quot; id=&quot;markdown-toc-semantics-and-completion&quot;&gt;Semantics and Completion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gnu-blobal&quot; id=&quot;markdown-toc-gnu-blobal&quot;&gt;GNU BLOBAL&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#universal-ctags&quot; id=&quot;markdown-toc-universal-ctags&quot;&gt;Universal Ctags&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#emerge-global&quot; id=&quot;markdown-toc-emerge-global&quot;&gt;Emerge GLOBAL&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ggtags&quot; id=&quot;markdown-toc-ggtags&quot;&gt;ggtags&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#pygments&quot; id=&quot;markdown-toc-pygments&quot;&gt;pygments&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#global-tag-database&quot; id=&quot;markdown-toc-global-tag-database&quot;&gt;GLOBAL tag database&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#usage&quot; id=&quot;markdown-toc-usage&quot;&gt;Usage&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#multiple-matches&quot; id=&quot;markdown-toc-multiple-matches&quot;&gt;Multiple matches&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#code-completion&quot; id=&quot;markdown-toc-code-completion&quot;&gt;Code Completion&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#header-file-completion&quot; id=&quot;markdown-toc-header-file-completion&quot;&gt;Header file completion&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#references&quot; id=&quot;markdown-toc-references&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This tutorial demonstrates the process of setting up a C/C++
development environment within Emacs. It mainly involves &lt;a href=&quot;http://www.gnu.org/software/global/&quot;&gt;GNU
GLOBAL&lt;/a&gt; and
&lt;a href=&quot;https://github.com/leoliu/ggtags&quot;&gt;ggtags&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;tag&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/q/12922526&quot;&gt;Tag&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;Tag is just an index file storing language objects from project
sources, which allows these objects to be quickly and easily located
and queried by text editors or other utilities.&lt;/p&gt;

&lt;p&gt;In regard to tag environment, we should differentiate concepts of
&lt;em&gt;command&lt;/em&gt; and &lt;em&gt;format&lt;/em&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;etags&lt;/code&gt; generates &apos;TAGS&apos; files understood by
Emacs while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt; generate &apos;tags&apos; files for Vi.&lt;/p&gt;

&lt;p&gt;&apos;tags&apos; format contains far richer metadata than &apos;TAGS&apos; format that
cannot be interpreted by Emacs. In spite of that, both formats are
more or less the same.&lt;/p&gt;

&lt;p&gt;Emacs package has built-in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;etags&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt; commands. There exist
other standalone package providing these commands, such as
&lt;a href=&quot;https://github.com/universal-ctags&quot;&gt;universal-ctags&lt;/a&gt; and
&lt;a href=&quot;http://ctags.sourceforge.net/&quot;&gt;exuberant-ctags&lt;/a&gt;(&lt;em&gt;deprecated&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Nowadays, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt; from &lt;em&gt;universal-ctags&lt;/em&gt; can generate TAGS format with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e&lt;/code&gt; option. Hence, we can concentrate on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt;. Besides, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt;
supports more languages.&lt;/p&gt;

&lt;p&gt;Another package &lt;a href=&quot;http://cscope.sourceforge.net/&quot;&gt;cscope&lt;/a&gt; that is more
powerful than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt; is, in reality, dead. Originally, it encompasses
much more features, especially when C and C++ are concerned. Moreover,
it has its own tag database unlike plain-text format. You will find,
from this tutorial, that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cscope&lt;/code&gt; is silimar to GNU GLOBAL but support
fewer languages.&lt;/p&gt;

&lt;h1 id=&quot;semantics-and-completion&quot;&gt;Semantics and Completion&lt;/h1&gt;

&lt;p&gt;Tag only cares about sources navigation. Upon writing code, we want
semantic parser to understand source objects and then achieve auto
completion.&lt;/p&gt;

&lt;p&gt;There exists a host of auto-completion packages, like
&lt;a href=&quot;https://github.com/company-mode/company-mode&quot;&gt;company-mode&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;gnu-blobal&quot;&gt;&lt;a href=&quot;http://www.gnu.org/software/global/&quot;&gt;GNU BLOBAL&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;GNU GLOBAL is an universal source code tagging system across diverse
platforms and environments, such as Emacs, Vim, Bash Shell, various
web browsers.&lt;/p&gt;

&lt;p&gt;Through the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global&lt;/code&gt;, we can easily locate various objects,
such as functions, macros, structs, classes etc. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gtags&lt;/code&gt; command
is similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;etags&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt;, but is different from them in the
following two points:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Independence of any editor;&lt;/li&gt;
  &lt;li&gt;Capability to treat both definition and reference;&lt;/li&gt;
  &lt;li&gt;Tag database support.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GLOBAL supports 6 langages as C, C++, Yacc, Java, PHP4 and assembly by
built-in semantic parser. Actually, GLOBAL brings along &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gtags-cscope&lt;/code&gt;
support which, though outdated, can replace the default parser when
parsing C/C++.&lt;/p&gt;

&lt;p&gt;To support a wider range, we can combine GLOBAL, Pygments,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;etags&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt; plug-in parser. As mentioned above, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt; is a
superset of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;etags&lt;/code&gt;. Ideally, we prefer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt; of &lt;em&gt;universal-ctags&lt;/em&gt;
over the built-in one of Emacs.&lt;/p&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;h2 id=&quot;universal-ctags&quot;&gt;Universal Ctags&lt;/h2&gt;

&lt;p&gt;Before &lt;em&gt;make&lt;/em&gt; GLOBAL, we should build
&lt;a href=&quot;https://github.com/universal-ctags&quot;&gt;universal-ctags&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt;. The
goal is to replace the default &lt;em&gt;/usr/bin/ctags&lt;/em&gt; from Emacs.&lt;/p&gt;

&lt;p&gt;Then supply&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./configure --prefix=&amp;lt;PREFIX&amp;gt; --with-exuberant-ctags=/usr/local/bin/ctags
# -or-
./configure --prefix=&amp;lt;PREFIX&amp;gt; --with-universal-ctags=/usr/local/bin/ctags
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;argument, telling GLOBAL where &lt;em&gt;universal-ctags&lt;/em&gt; locates.&lt;/p&gt;

&lt;p&gt;I won&apos;t discuss building &lt;em&gt;universal-ctags&lt;/em&gt; in this post and maybe get
back to topic later on. Instead, the default GLOBAL built-in parser is
enough for C/C++.&lt;/p&gt;

&lt;h2 id=&quot;emerge-global&quot;&gt;Emerge GLOBAL&lt;/h2&gt;

&lt;p&gt;Since GLOBAL is independent of editors, it requires imtermediate
bridges. To interact with Emacs, it has &lt;em&gt;gtags.el&lt;/em&gt;. We should enable
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emacs&lt;/code&gt; USE:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# echo &apos;dev-util/global emacs&apos; &amp;gt;&amp;gt; /etc/portage/package.use/global (opt)&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# emerge -avt dev-util/global&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Actually, Emacs also has &lt;em&gt;etags.el&lt;/em&gt; for default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;etags&lt;/code&gt; and &lt;em&gt;ctags.el&lt;/em&gt;
for default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;ggtags&quot;&gt;&lt;a href=&quot;https://github.com/leoliu/ggtags&quot;&gt;ggtags&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;However, &lt;em&gt;gtags.el&lt;/em&gt; is quite primitve, we would like the improved
version &lt;em&gt;ggtags&lt;/em&gt;. So just install &lt;em&gt;ggtags.el&lt;/em&gt; through ELPA
&lt;em&gt;list-packages&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;After installing &lt;em&gt;ggtags&lt;/em&gt;, add to &lt;em&gt;init.el&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;ggtags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;c-mode-common-hook&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;derived-mode-p&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;c-mode&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;c++-mode&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;java-mode&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;asm-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ggtags-mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another replacement is
&lt;a href=&quot;https://github.com/syohex/emacs-helm-gtags&quot;&gt;helm-gtags&lt;/a&gt;. I will leave
it to yourself.&lt;/p&gt;

&lt;h2 id=&quot;pygments&quot;&gt;&lt;a href=&quot;http://pygments.org/&quot;&gt;pygments&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;In order to support syntax highlighting, we need &lt;em&gt;pygments&lt;/em&gt;. It can be
installed through package manager or within Python virtual environment.&lt;/p&gt;

&lt;p&gt;After installing &lt;em&gt;pygments&lt;/em&gt;, we also require an intermediate plugin
for GLOBAL, namely &lt;a href=&quot;https://github.com/yoshizow/global-pygments-plugin&quot;&gt;Pygments Plug-in Parser for GNU
GLOBAL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since 6.3.2, GLOBAL includes it by default. For older version, we
should install it manually.&lt;/p&gt;

&lt;h1 id=&quot;global-tag-database&quot;&gt;GLOBAL tag database&lt;/h1&gt;

&lt;p&gt;A tag is a name of an object/entity in source code. An object can be a
variable, a method definition, an include-operator …&lt;/p&gt;

&lt;p&gt;A tag contains information like name of the entity, location in the
source code, and which source file it belongs to.&lt;/p&gt;

&lt;p&gt;GNU GLOBAL makes use of three tag databases:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;GTAGS&lt;/th&gt;
      &lt;th&gt;definition database&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;GRTAGS&lt;/td&gt;
      &lt;td&gt;reference database&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;GPATH&lt;/td&gt;
      &lt;td&gt;path name database&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;A definition of a tag is where the tag is implemented (&lt;em&gt;not&lt;/em&gt;
declaration). For example, a function definition is the block where
the function is actually implemented.&lt;/p&gt;

&lt;p&gt;On the contrary, a reference of a tag is where it is used in a source
tree, but not where it is defined.&lt;/p&gt;

&lt;h1 id=&quot;usage&quot;&gt;Usage&lt;/h1&gt;

&lt;p&gt;Up to now, we have almost finished the installation and configuration
process. Next, we will examine how these components collaborate with
each other to achieve an intelligent development environment.&lt;/p&gt;

&lt;p&gt;The most commonly used command is &lt;em&gt;ggtags-find-tag-dwim&lt;/em&gt; bound to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-.&lt;/code&gt;, which &lt;em&gt;find a tag by context&lt;/em&gt;. It will jump to a reference if
the tag at point is a definition. Rather, it will jump to a definition
if the tag at point is a reference. The the tag at point is a
&lt;em&gt;include&lt;/em&gt; header, it jumps to that header file.&lt;/p&gt;

&lt;p&gt;Other useful functions are:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;ggtags-find-definition&lt;/th&gt;
      &lt;th&gt;find definition tags&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ggtags-find-reference&lt;/td&gt;
      &lt;td&gt;find reference tags&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ggtags-find-other-symbol&lt;/td&gt;
      &lt;td&gt;find tags that have no definitions&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ggtags-find-tag-regexp&lt;/td&gt;
      &lt;td&gt;find definition tags by &lt;em&gt;regexp&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ggtags-query-replace&lt;/td&gt;
      &lt;td&gt;do a query &amp;amp; replace in all files found in a search&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ggtags-find-file&lt;/td&gt;
      &lt;td&gt;find a file from all the files indexed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gtags&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ggtags-visit-project-root&lt;/td&gt;
      &lt;td&gt;open the project root in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dired&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;multiple-matches&quot;&gt;Multiple matches&lt;/h2&gt;

&lt;p&gt;When a search find multiple matches, a new buffer named
&lt;em&gt;ggtags-global&lt;/em&gt; is created and &lt;em&gt;ggtags-navigation-mode&lt;/em&gt; is enabled to
faciliate entry selection by following commands:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;M-n&lt;/th&gt;
      &lt;th&gt;move to the next match&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;M-p&lt;/td&gt;
      &lt;td&gt;move to the previous match&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;M-}&lt;/td&gt;
      &lt;td&gt;move to the next file&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;M-{&lt;/td&gt;
      &lt;td&gt;move to the previous file&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;M-=&lt;/td&gt;
      &lt;td&gt;move to the file where navigation session starts&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;M-&amp;lt;&lt;/td&gt;
      &lt;td&gt;move to the first match&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;M-&amp;gt;&lt;/td&gt;
      &lt;td&gt;move to the last match&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;C-M-s, M-s s&lt;/td&gt;
      &lt;td&gt;use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isearch&lt;/code&gt; to find a match&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;M-,&lt;/td&gt;
      &lt;td&gt;abort and go back to the location where search was started&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;code-completion&quot;&gt;Code Completion&lt;/h1&gt;

&lt;p&gt;Install &lt;a href=&quot;https://github.com/company-mode/company-mode&quot;&gt;company-mode&lt;/a&gt;
and add to &lt;em&gt;init.el&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;company&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; optional&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;after-init-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;global-company-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, &lt;em&gt;company-clang&lt;/em&gt; backend to retrieve standard libraries
(&lt;em&gt;/usr/include/&lt;/em&gt;) but not our project files. We can make use of
&lt;em&gt;company-complete&lt;/em&gt; that encompasses &lt;em&gt;company-clang&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;company-backends&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;company-semantic&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;company-backends&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; optional&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c-mode-map&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;company-complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;define-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c++-mode-map&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tab&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;company-complete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By this snippet, we use &apos;company-complete&apos; which calls &apos;company-clang&apos;
on demand while completes project entities. The very first reference
suggests deleting &lt;em&gt;company-semantic&lt;/em&gt; from &lt;em&gt;company-backends&lt;/em&gt;. However,
as far as I know, it is unneccessary.&lt;/p&gt;

&lt;p&gt;Then we resort to &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html&quot;&gt;GNU Emacs Manual - Per-Directory Local
Variables&lt;/a&gt;,
creating a special file &lt;em&gt;.dir-locals.el&lt;/em&gt; under our project root. This
file is usually used to define directory-local variables.&lt;/p&gt;

&lt;p&gt;Emacs will read it when it visits any file in that directory or any of
its subdirectories, and apply the settings it specifies to the file&apos; s
buffer.&lt;/p&gt;

&lt;p&gt;We set &lt;em&gt;company-clang-arguments&lt;/em&gt; in this file, specifying the project
header files&apos; location, namly the &lt;em&gt;include path&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;company-clang-arguments&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;-I/home/&amp;lt;user&amp;gt;/project_root/include1/&quot;&lt;/span&gt;
                                     &lt;span class=&quot;s&quot;&gt;&quot;-I/home/&amp;lt;user&amp;gt;/project_root/include2/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That is enough! &lt;em&gt;company-clang&lt;/em&gt; is able to retrieve completion
candidates from our project sources.&lt;/p&gt;

&lt;h2 id=&quot;header-file-completion&quot;&gt;Header file completion&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/randomphrase/company-c-headers&quot;&gt;company-c-headers&lt;/a&gt;
helps complete &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#include&lt;/code&gt; statements by searching header filenames.&lt;/p&gt;

&lt;p&gt;After installation, add to &lt;em&gt;init.el&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;company-backends&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;company-c-headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, &lt;em&gt;company-c-headers&lt;/em&gt; only covers C headers under
&lt;em&gt;/usr/include/&lt;/em&gt; and &lt;em&gt;/usr/local/include/&lt;/em&gt;. To support C++ headers, we
should:&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;company-c-headers-path-system&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/usr/include/c++/4.8/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Simiarly, to complete projects header files, set
&lt;em&gt;company-c-headers-path-user&lt;/em&gt; in &lt;em&gt;.dir-locals.el&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://tuhdo.github.io/c-ide.html&quot;&gt;C/C++ Development Environment for Emacs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/universal-ctags/ctags&quot;&gt;Universal Ctags&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/leoliu/ggtags&quot;&gt;ggtags&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/global/global.html&quot;&gt;GNU GLOBAL&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>MTP</title>
   <link href="/2018/07/18/mtp/"/>
   <updated>2018-07-18T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/07/18/mtp</id>
   <content type="html">&lt;p&gt;MTP (Media Transfer Protocol) is a protocol to allow the transfer of files to external devices. It is provided by several programs, most of them depending on FUSE.&lt;/p&gt;

&lt;p&gt;From both the iOS and Android posts, we resort to Thunar (with &lt;em&gt;gvfs&lt;/em&gt; support). In this post, I will show manually how to manage MTP device (Windows phone, Android, and even Creative Zen player) files. Irrespective of methods adopted, almost all packages implementing MTP depend on &lt;em&gt;libmtp&lt;/em&gt; and/or FUSE.&lt;/p&gt;

&lt;p&gt;Android doesn&apos;t support mounting your phone as a USB mass storage device anymore (from Android 3.0 onwards). Instead, put device into MTP mode and then access to device through MTP package. Take Android for instance, upon connected to computer, the device would prompts you to choose the mode, usually writing &quot;charging only&quot;, &quot;transmit files&quot; and &quot;tansmit photos&quot;. Just select the 2nd option.&lt;/p&gt;

&lt;p&gt;There are a bunch of MTP packages like &lt;em&gt;mtpfs&lt;/em&gt;, &lt;em&gt;go-mtpfs&lt;/em&gt;, &lt;em&gt;jmtpfs&lt;/em&gt; etc. Specially, &lt;em&gt;gphotofs&lt;/em&gt; is a FUSE-based file system for interfacing with digital cameras using the &lt;em&gt;gphoto2&lt;/em&gt; application.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;mtpfs&lt;/em&gt; is almost orphaned. Here I will take &lt;em&gt;jmtpfs&lt;/em&gt; for example. Please make sure:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Relevant Udev rule is created for your device like that in Android post.&lt;/li&gt;
  &lt;li&gt;Also check if user belongs to &lt;em&gt;plugdev&lt;/em&gt; group.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt jmtpfs&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; ~/mnt
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;jmtpfs &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; jmtpfs &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;jmtpfs ~/mnt
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; ~/mnt
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fusermount &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; ~/mnt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That&apos;s all!&lt;/p&gt;

&lt;p&gt;To simplify the process by regular &lt;em&gt;mount&lt;/em&gt;, we create &lt;em&gt;jmtpfs&lt;/em&gt; entry in &lt;em&gt;/etc/fstab&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Firstly, make symbolic similar to &lt;em&gt;mount.fuse&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# ln -sv /usr/bin/jmtpfs /usr/bin/mount.jmtpfs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, add to &lt;em&gt;/etc/fstab&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/fstab

jmtpfs /home/user/run/motog fuse noauto,noatime,nodev,user,uid=1000,gid=1000 0 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of the options, &lt;em&gt;user&lt;/em&gt; means any other accounts besides &lt;em&gt;root&lt;/em&gt; can &lt;em&gt;mount&lt;/em&gt; the entry.&lt;/p&gt;

&lt;p&gt;Finally:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mount ~/run/motog
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; ~/run/motog
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Interestingly, you will find even &lt;em&gt;root&lt;/em&gt; cannot access to &lt;em&gt;/home/user/run/motog&lt;/em&gt;, which is FUSE security restriction! What is more, &lt;em&gt;umount&lt;/em&gt; is not allowed. Check man page of &lt;em&gt;mount.fuse&lt;/em&gt;. To allow other accounts and/or &lt;em&gt;root&lt;/em&gt; to read/write device files and &lt;em&gt;umount&lt;/em&gt;, we should turn on &apos;user_allow_other&apos; option in FUSE configuration &lt;em&gt;/etc/fuse.conf&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/fuse.conf

# Allow non-root users to specify the &apos;allow_other&apos; or &apos;allow_root&apos;
# mount options.
#
user_allow_other
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Append &apos;allow_other&apos; or &apos;allow_root&apos; to mounting options. Before this takes effect, remember to reboot system:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/fstab

jmtpfs /home/user/run/motog fuse noauto,noatime,nodev,user,allow_root,uid=1000,gid=1000 0 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Up to now, I have demonstrated mounting MTP devices and file permissions thereof. To detach the device, most &lt;em&gt;libmtp&lt;/em&gt; based packages resort to &lt;em&gt;fusermount&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fusermount &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; ~/run/motog
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If &apos;allow_other&apos; or &apos;allow_root&apos; is enabled, then use &lt;em&gt;umount&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;umount ~/run/motog
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Bitcoin Whitepaper</title>
   <link href="/2018/06/13/bitcoin-whitepaper/"/>
   <updated>2018-06-13T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/06/13/bitcoin-whitepaper</id>
   <content type="html">&lt;p&gt;Bitcoin&lt;/p&gt;

&lt;h1 id=&quot;p2p-timestamp-system&quot;&gt;p2p timestamp system&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;chronological cryptography vs trust on 3rd party institution;&lt;/li&gt;
  &lt;li&gt;solve double-spending issue;&lt;/li&gt;
  &lt;li&gt;depends on the fact that honest nodes collectively outpace attacker nodes;&lt;/li&gt;
  &lt;li&gt;proof-of-work;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;transaction&quot;&gt;transaction&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;we mine a block (and get coin reward) istead of a coin; bitcoins are created each time a user discovers a new block.&lt;/li&gt;
  &lt;li&gt;coin is defined as a set of transactions digitally signed; payee can verify the payer and cannot verify whether it&apos;s the earliest transaction, thus cannot exclude double-spending;&lt;/li&gt;
  &lt;li&gt;all transactions are publicly announced;&lt;/li&gt;
  &lt;li&gt;a transaction has inputs (several) and outputs (at most 2). Inputs are existing outputs from other transactions for you. Hence, transaction actually takes outputs for you and then generate new outputs, one of which is for payee and the other is for change. The remaining (sum of inputs minus sum of outputs) is Bitcoin fee.&lt;/li&gt;
  &lt;li&gt;we need &apos;change&apos; because outputs cannot be partially spent. You can only spend your output as a whole, which explains why we could have &apos;change&apos; output.&lt;/li&gt;
  &lt;li&gt;wallet (account balance) of a peer (identified by private key) is derived from all transaction outputs for his public key, namely &apos;pay-to-pubkey-hash&apos; transactions.&lt;/li&gt;
  &lt;li&gt;To get the concept of transactoin, read https://bitcoin.stackexchange.com/a/20623 and https://bitcoin.stackexchange.com/q/736&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;block reward = block subsidy + transactions fees&lt;/p&gt;

&lt;h1 id=&quot;timestamp-server&quot;&gt;timestamp server&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;another hash on the whole transaction block;&lt;/li&gt;
  &lt;li&gt;each item in the block consists of a transaction and timestamp thereof; transaction items in a block are usually unrelated.&lt;/li&gt;
  &lt;li&gt;payee can verify it is the earliest and not a double-spending transaction. kick out double-spending transaction.&lt;/li&gt;
  &lt;li&gt;announce the hash and timestamp together.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;proof-of-work&quot;&gt;proof-of-work&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;how to hash? simple sha-256 is not enough! Add nonce to find a special hash value that starts with a number of zero bits. The number is increased overtime (more and more difficult).&lt;/li&gt;
  &lt;li&gt;proof-of-work is where our &apos;mining resources&apos; are invested and represented by &apos;minining resources&apos; invested.&lt;/li&gt;
  &lt;li&gt;proof-of-work is deliberately designed to avoid double-spending such that attacker cannot catch up.&lt;/li&gt;
  &lt;li&gt;Nodes compete to confirm a transaction, namely compete to tally!&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;p2p-networking-process&quot;&gt;p2p networking process&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;new transaction is simply hashed and signed before announcement.&lt;/li&gt;
  &lt;li&gt;a block (local copy) comprises a set of transaction items, previous hash, nounce. received transaction along with timestamp are inserted into the transaction set.&lt;/li&gt;
  &lt;li&gt;difficult hash computational work for block, namely proof-of-work.&lt;/li&gt;
  &lt;li&gt;success! a peer announces hash and the block.&lt;/li&gt;
  &lt;li&gt;other peers verify and accept the block.&lt;/li&gt;
  &lt;li&gt;other peers create a new block by replacing the &apos;Prev Hash&apos; field and announce it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Conceptually, there is only one valid (of course longest) blockchain over the network. But techniquely, there exist mutiple blockchains simutaneouly due to node joining/leaving, network latency, forks etc.&lt;/p&gt;

&lt;h1 id=&quot;double-spending&quot;&gt;double-spending&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Timestamp is acutally not critical element since attacker node can forge local time. Instead, the longest blockchain is accepted while other candidates are discarded.&lt;/li&gt;
  &lt;li&gt;Currently, user confirm a transaction if it buried over 6 (included) blocks. 6 blockes are enough to avoid catching up by powerful attacker. If an attacker double-spends coins by signing second transaction immediately (say one to Alice and another to Bob), only one of them (say that to Bob) is accepted when it is buried in a longer blockchain.&lt;/li&gt;
  &lt;li&gt;It is not really the Proof of Work which prevents double spends but rather the blockchain itself which prevents double spends. The Proof of Work is just one aspect of the blockchain.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Freshly-mined coins cannot be spent for 100 blocks. It is advisable to wait some additional time for a better chance that the transaction will be propagated by all nodes. Some older bitcoin clients won&apos;t show generated coinsas confirmed until they are 120 blocks deep.&lt;/p&gt;

    &lt;p&gt;Blockchain forks might cause oprphan blocks. Suppose a block owner spends the subsidy and rewards (newly coins), and get 6 confirmations. However, 6 is too small to guarantee that the new block would finally merged into mainnet. Maybe this block will be orphaned and newly coins disappear as well.&lt;/p&gt;

    &lt;p&gt;The key is that transaction with coinbase coins input has no source! We cannot track back! For transaction with old coins input, we can track back to other transaction output. Even though the block container become orphan, it will be confirmed by other block afterwards.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;https://bitcoin.stackexchange.com/q/61385&lt;/p&gt;

&lt;h1 id=&quot;incentive&quot;&gt;incentive&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;the first transaction in a block is a special transaction that starts a new coin owned by the creator of the block; the transaction set is empty.&lt;/li&gt;
  &lt;li&gt;transaction fees; fee is given to the peer that achieve &apos;proof-of-work&apos; - the one that find a block. Bitcoin fee is fixed independently of the amount of coins.&lt;/li&gt;
  &lt;li&gt;attacker with more mining resources probably chooses to be honest as that would earn more coins than stealing.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;privacy&quot;&gt;privacy&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;peer public key is anonymous though transactions are public.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;economy&quot;&gt;Economy&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Bitcoin amount limit would fail in &lt;em&gt;deflation spiral&lt;/em&gt;. But that is not a problem as Bitcoin cannot be global currency.&lt;/li&gt;
  &lt;li&gt;Currently, miners mine bitcoins assuming price increase in the future.&lt;/li&gt;
  &lt;li&gt;People use bitcoins to bypass censorship.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;中文&quot;&gt;中文&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;账本，区块链，blockchain;&lt;/li&gt;
  &lt;li&gt;矿池，asic hwardware node;&lt;/li&gt;
  &lt;li&gt;挖矿，mine, proof-of-work, hash with leading zeros;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;todos&quot;&gt;todos&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;asic hardware;&lt;/li&gt;
  &lt;li&gt;testnet for fun;&lt;/li&gt;
  &lt;li&gt;p2p timestamp? what if fake node time?&lt;/li&gt;
  &lt;li&gt;centralized Bitcoin exchange?&lt;/li&gt;
  &lt;li&gt;how many bits of a hash is required?&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;reference&quot;&gt;reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Bitcoin: A Peer-to-Peer Electronic Cash System&lt;/li&gt;
  &lt;li&gt;https://en.bitcoin.it/wiki/Controlled_supply&lt;/li&gt;
  &lt;li&gt;https://bitcoin.org/en/how-it-works&lt;/li&gt;
  &lt;li&gt;https://bitcoin.org/en/you-need-to-know&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Awesome</title>
   <link href="/2018/06/10/awesome/"/>
   <updated>2018-06-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/06/10/awesome</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#rclua&quot; id=&quot;markdown-toc-rclua&quot;&gt;rc.lua&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#x-terminal-emulator&quot; id=&quot;markdown-toc-x-terminal-emulator&quot;&gt;X terminal emulator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#autostart&quot; id=&quot;markdown-toc-autostart&quot;&gt;Autostart&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#menu&quot; id=&quot;markdown-toc-menu&quot;&gt;Menu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#theme&quot; id=&quot;markdown-toc-theme&quot;&gt;Theme&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wallpaper&quot; id=&quot;markdown-toc-wallpaper&quot;&gt;wallpaper&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#transparency&quot; id=&quot;markdown-toc-transparency&quot;&gt;Transparency&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#screenshot&quot; id=&quot;markdown-toc-screenshot&quot;&gt;Screenshot&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#slock&quot; id=&quot;markdown-toc-slock&quot;&gt;slock&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#xautolock&quot; id=&quot;markdown-toc-xautolock&quot;&gt;xautolock&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#st-terminal-emulator&quot; id=&quot;markdown-toc-st-terminal-emulator&quot;&gt;st terminal emulator&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Awesome is a lightweight window manager and yet can be highly cusotmized to your own needs. This post mainly focuses on awesome configuration at &lt;em&gt;~/.config/awesome/rc.lua&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;rclua&quot;&gt;rc.lua&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; .config/awesome
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /etc/xdg/awesome/rc.lua ~/.config/awesome/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Super-s&lt;/code&gt; to show key bindings.&lt;/p&gt;

&lt;h1 id=&quot;x-terminal-emulator&quot;&gt;X terminal emulator&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://st.suckless.org/&quot;&gt;st&lt;/a&gt; and &lt;a href=&quot;https://github.com/Tetralet/LilyTerm&quot;&gt;lilyterm&lt;/a&gt; are recommended in that they are lightweight and supports UTF8 and CJK by nature.&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- rc.lua&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;terminal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;st&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check syntax:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# awesome -k&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-Super-r&lt;/code&gt; to reload &lt;em&gt;rc.lua&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;autostart&quot;&gt;Autostart&lt;/h1&gt;

&lt;p&gt;Desktop (XFCE, KDE etc.) has many autostart &lt;em&gt;.desktop&lt;/em&gt; files in &lt;em&gt;/etc/xdg/autostart/&lt;/em&gt; or &lt;em&gt;~/.config/autostart/&lt;/em&gt; to launch default applications on startup (i.e. input method, power manager etc.). Awesome requires manual settings:&lt;/p&gt;

&lt;p&gt;Here is an example of VBoxClient-all autostart with awesome. Create &lt;em&gt;~/.config/awesome/autostart.sh&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;run &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; pgrep &lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&amp;amp;
  &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

run VBoxClient-all
run fcitx-autostart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make it executable:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;user@host ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x ~/.config/awesome/autostart.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check &lt;em&gt;autostart.sh&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;user@host ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;~/.config/awesome/autostart.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can add any other programs to autostart by appending &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run executable [--arguments]&lt;/code&gt; to the end of &lt;em&gt;autostart.sh&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Finally, add to the end of &lt;em&gt;~/.config/awesome/rc.lua&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- awful.spawn.with_shell(&quot;~/.config/awesome/autostart.sh&quot;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;with_shell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/autostart.sh&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please be noted that, awesome restart does not restart scripts in &lt;em&gt;autostart.sh&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;menu&quot;&gt;Menu&lt;/h1&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- rc.lua&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;myawesomemenu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hotkeys&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hotkeys_popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show_help&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;focused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;manual&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;terminal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; -e man awesome&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;edit config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;editor_cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot; &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awesome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;conffile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;aw restart&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awesome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;restart&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;aw quit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awesome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- systemd-logind allows unpriviledged users to shutdown system&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;shutdownmenu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;hibernate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;systemctl hibernate&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;suspend&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;systemctl suspend&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;reboot&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;systemctl reboot&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;shutdown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;systemctl poweroff&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;appsmenu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;emacs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;emacs&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;thunar&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;thunar&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;firefox&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;firefox&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;chrome&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;chromium&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;telegram&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;telegram-desktop&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;settingsmenu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sound&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;st -e alsamixer&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;mymainmenu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;menu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;awesome&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myawesomemenu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beautiful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awesome_icon&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                                    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;shutdown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shutdownmenu&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                                    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;settings&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;settingsmenu&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                                    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;applications&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;appsmenu&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                                    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;files&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;thunar&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                                    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;editor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;emc&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                                    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;browser&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;firefox&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
                                    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;terminal&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;terminal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                                  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Trigger menu bar by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mod-p&lt;/code&gt; binding and then type the application keywords.&lt;/p&gt;

&lt;h1 id=&quot;theme&quot;&gt;Theme&lt;/h1&gt;

&lt;p&gt;First, we create per-user theme directory and copy default theme there where we will do customization.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/.config/awesome/themes/
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; /usr/share/awesome/themes/default/ ~/.config/awesome/themes/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Afterwards, change &lt;em&gt;beautiful.wallpaper&lt;/em&gt; value to the new directory in &lt;em&gt;rc.lua&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- rc.lua&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- beautiful.init(gears.filesystem.get_themes_dir() .. &quot;default/theme.lua&quot;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;beautiful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/themes/default/theme.lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- or&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;beautiful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_configuration_dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/themes/default/theme.lua&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For example, we can set useless gap to 5:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- rc.lau&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;beautiful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;useless_gap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;wallpaper&quot;&gt;wallpaper&lt;/h1&gt;

&lt;p&gt;To set a wallpaper, change &lt;em&gt;theme.wallpaper&lt;/em&gt; value in &lt;em&gt;theme.lua&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- theme.lua&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wallpaper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;~/.config/awesome/themes/default/wallpaper.png&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, we can set wallpaper in &lt;em&gt;rc.lua&lt;/em&gt; before function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set_wallpaper(s)&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- rc.lua&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;beautiful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wallpaper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_configuration_dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sub-path/to/wallpaper.png&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;transparency&quot;&gt;Transparency&lt;/h1&gt;

&lt;p&gt;For &lt;em&gt;wibox&lt;/em&gt; transparency, append transparency value (00 - FF) to &lt;em&gt;bg_normal&lt;/em&gt; in &lt;em&gt;theme.lua&lt;/em&gt;. 00 means totally transparent while FF is not transparent.&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- theme.lua&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;--theme.bg_normal     = &quot;#222222&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bg_normal&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;#22222200&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, append &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bg = beautiful.bg_normal .. &quot;0&quot;&lt;/code&gt; to &lt;em&gt;s.mywibox&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- rc.lua&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mywibox&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wibar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;top&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;screen&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beautiful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bg_normal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;00&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;screenshot&quot;&gt;Screenshot&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt scrot&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;scrot &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-q50&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cd3&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add to the &lt;em&gt;globalkeys&lt;/em&gt; array:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- rc.lua&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Print&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;scrot -s -q50 -e &apos;mv $f ~/Desktop/ 2&amp;gt;/dev/null&apos;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;take screenshot&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;launcher&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- or&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Print&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spawn_with_shell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;scrot -s -q50 -e &apos;mv $f ~/Desktop/ 2&amp;gt;/dev/null&apos;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;take screenshot&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;launcher&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pay attention to the &lt;em&gt;nil&lt;/em&gt; part, otherwise we could not take screenshot with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-s&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;slock&quot;&gt;slock&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# echo &apos;x11-misc/slock savedconfig&apos; &amp;gt;&amp;gt; /etc/portage/package.use/slock&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt slock (Additionally, I have add in the *dpms* patch.)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Set key binding:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;-- rc.lua&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modkey&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;l&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;slock&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;lock screen&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;XF86ScreenSaver&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;awful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;slock&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;lock screen&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XF86ScreenSaver&lt;/code&gt; means &lt;em&gt;Fn + F2&lt;/em&gt; key combination. To determine the key name, just press relevant key or binding in Emacs GUI or resort to &lt;em&gt;sev&lt;/em&gt;, &lt;em&gt;showkey&lt;/em&gt; &lt;em&gt;xmodkey&lt;/em&gt; etc.&lt;/p&gt;

&lt;p&gt;To prevent from &lt;a href=&quot;/2019/03/11/x/&quot;&gt;virtual terminal&lt;/a&gt; switching or killing X, use the following Xorg config:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# 30-slock.conf
Section &quot;ServerFlags&quot;
    Option &quot;DontVTSwitch&quot; &quot;True&quot;
    Option &quot;DontZap&quot;      &quot;True&quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Otherwise, screenlock is meaningless.&lt;/p&gt;

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

&lt;p&gt;To automatically lock screen after a period of inactivity, we use &lt;em&gt;xautolock&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt xautolock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We create a script autostart script &lt;em&gt;~/opt/bin/xautoslock.sh&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;xautolock &lt;span class=&quot;nt&quot;&gt;-detectsleep&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;-time&lt;/span&gt; 3 &lt;span class=&quot;nt&quot;&gt;-locker&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;slock&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;-corners&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;00+0&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cornerdelay&lt;/span&gt; 10 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;-notify&lt;/span&gt; 10 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;-notifier&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;notify-send -u critical -t 10000 -- &apos;LOCKING screen in 10 seconds&apos;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, assign executable permission (&lt;em&gt;chmod +x xautoslock.sh&lt;/em&gt;) before appending it to &lt;em&gt;autostart.sh&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;run ~/opt/bin/xautoslock.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;st-terminal-emulator&quot;&gt;st terminal emulator&lt;/h1&gt;

&lt;p&gt;Firstly, we enable &lt;em&gt;savedconfig&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# echo &apos;x11-terms/st savedconfig&apos; &amp;gt;&amp;gt; /etc/portage/package.use/st&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;st is quite basic and lack features like copy/paste, scrollback etc. We should apply a few local patches by &lt;a href=&quot;https://wiki.gentoo.org/wiki//etc/portage/patches&quot;&gt;/etc/portage/patches&lt;/a&gt; before they are merged into portage:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# make sure the slot number is correct&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# mkdir -p /etc/portage/patches/x11-terms/st-0.7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the directory made does not contain version and/or slot specifier (&lt;em&gt;/etc/portage/patches/x11-terms/st/&lt;/em&gt;), then everytime you emerge (i.e. update) the package, patches are definitely applied, which would fail if new versions in portage already apply the patches, causing patches to be applied twice.&lt;/p&gt;

&lt;p&gt;Grab &lt;a href=&quot;http://st.suckless.org/patches/&quot;&gt;patch files&lt;/a&gt; from st official page and put them into directory just created. &lt;em&gt;clipboard&lt;/em&gt;, &lt;em&gt;scrollback&lt;/em&gt;, &lt;em&gt;spoiler&lt;/em&gt;, &lt;em&gt;visualbell&lt;/em&gt;, &lt;em&gt;xresources&lt;/em&gt; and &lt;em&gt;solarized&lt;/em&gt; are recommended. &lt;em&gt;solarized-both-0.8.1&lt;/em&gt; has bug and please use &lt;em&gt;solarized-dark-0.8.1&lt;/em&gt; instead.&lt;/p&gt;

&lt;p&gt;Sometimes, a patch must be applied before another, we can rename the patch files with number prefix as patches are apllied in lexicographical order.&lt;/p&gt;

&lt;p&gt;Then step into the package&apos;s ebuild directory and check patches:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# cd /us/portage/x11-terms/st&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# ebuild st-0.7.ebuild clean prepare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We get the following log:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* st-0.7.tar.gz BLAKE2B SHA512 size ;-) ...
&amp;gt;&amp;gt;&amp;gt; Unpacking source...
&amp;gt;&amp;gt;&amp;gt; Unpacking st-0.7.tar.gz to /var/tmp/portage/x11-terms/st-0.7/work
&amp;gt;&amp;gt;&amp;gt; Source unpacked in /var/tmp/portage/x11-terms/st-0.7/work
&amp;gt;&amp;gt;&amp;gt; Preparing source in /var/tmp/portage/x11-terms/st-0.7/work/st-0.7 ...
* Applying st-clipboard-0.7.diff ...
* Applying st-scrollback-0.7.diff ...
* User patches applied.
* Checking existence of //etc/portage/savedconfig//x11-terms/st-0.7 ...
* found //etc/portage/savedconfig//x11-terms/st-0.7
* Building using saved configfile //etc/portage/savedconfig//x11-terms/st-0.7
&amp;gt;&amp;gt;&amp;gt; Source prepared.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We find a line &lt;em&gt;User patches applied&lt;/em&gt;. Bt this patching method, there is no need to update ebuild as long as it is EAPI6 and/or include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eapply_user&lt;/code&gt; instruction.&lt;/p&gt;

&lt;p&gt;st behaviour could be further adjusted from &lt;em&gt;savedconfig&lt;/em&gt;. By default, a copy will be saved as &lt;em&gt;/etc/portage/savedconfig/x11-terms/st-0.7&lt;/em&gt;. For example, we can change default shell, &lt;em&gt;termname&lt;/em&gt;, font, etc. To avoid re-compiling upon configuration update, we apply &lt;a href=&quot;https://st.suckless.org/patches/xresources/&quot;&gt;xresources&lt;/a&gt; patch that supports Xresources.&lt;/p&gt;

&lt;p&gt;If a patch happended to update &lt;em&gt;saveconfig&lt;/em&gt; USE, and later on you removed the patch. The compiling would be probably fail! Either remove saved config or take back the patch.&lt;/p&gt;

&lt;p&gt;Finally, just emerge!&lt;/p&gt;

&lt;p&gt;As of 0.7, the scrollback patch ignores saved config and report &lt;a href=&quot;https://lists.suckless.org/dev/1609/30495.html&quot;&gt;&lt;em&gt;histsize undeclared&lt;/em&gt;&lt;/a&gt;. Either bump to new slot or remove saved config file.&lt;/p&gt;

&lt;p&gt;To change &lt;em&gt;termname&lt;/em&gt; to &lt;em&gt;xterm-256color&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ~/.Xresources

st.termname: xterm-256color
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>ENG phonetics</title>
   <link href="/2018/06/06/eng-phonetics/"/>
   <updated>2018-06-06T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/06/06/eng-phonetics</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#references&quot; id=&quot;markdown-toc-references&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tips&quot; id=&quot;markdown-toc-tips&quot;&gt;Tips&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ipa&quot; id=&quot;markdown-toc-ipa&quot;&gt;IPA&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#发音过程&quot; id=&quot;markdown-toc-发音过程&quot;&gt;发音过程&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#vowel-vs-consonant&quot; id=&quot;markdown-toc-vowel-vs-consonant&quot;&gt;Vowel vs. Consonant&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#长短元音符号&quot; id=&quot;markdown-toc-长短元音符号&quot;&gt;长短元音符号&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#syllable-音节&quot; id=&quot;markdown-toc-syllable-音节&quot;&gt;Syllable 音节&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.bbc.co.uk/learningenglish/english/features/pronunciation&quot;&gt;BBC pronunciation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/English_phonology%23Sonorants&quot;&gt;english phonology&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://soundsofspeech.uiowa.edu/&quot;&gt;iowa phonetics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Cambrige: an international pronunciation course&lt;/li&gt;
  &lt;li&gt;American Accent Training&lt;/li&gt;
  &lt;li&gt;https://v.qq.com/x/page/w0146n8467c.html&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;tips&quot;&gt;Tips&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Open Open Open your mouth;&lt;/p&gt;

    &lt;p&gt;It means not only begin to practice, but keep your mouth and tongue movement to certain extent, speaking loud.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Check dictionary.&lt;/li&gt;
  &lt;li&gt;Film and TV series are not a proper guide. Use standard prounciation materials.&lt;/li&gt;
  &lt;li&gt;Improve intonation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ipa&quot;&gt;&lt;a href=&quot;/assets/IPA_chart_2018.pdf&quot;&gt;IPA&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;The International Phonetic Alphabet (IPA) is an alphabetic system of phonetic notation based primarily on the Latin alphabet.&lt;/p&gt;

&lt;p&gt;The IPA is designed to represent only those qualities of speech that are part of oral language: phones, phonemes, intonation and the separation of words and syllables.&lt;/p&gt;

&lt;p&gt;IPA symbols are composed of one or more elements of two basic types, letters and diacritics （变音符号）. English letter ⟨t⟩ may be transcribed in IPA with a single letter, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[t]&lt;/code&gt;, or with a letter plus diacritics, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[t̺ʰ]&lt;/code&gt;, depending on how precise one wishes to be. Often, slashes are used to signal broad （宽式注音） or phonemic transcription （音位注音，也称严式注音）; thus, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/t/&lt;/code&gt; is less specific than, and could refer to, either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[t̺ʰ]&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[t]&lt;/code&gt;, depending on the context and language.&lt;/p&gt;

&lt;p&gt;1888 年 8 月第一套国际音标符号诞生，这套符号设立的原则是：每一个独立的音都有一个独立的符号相对应，相同的符号在任何语言中都表示同一个发音。&lt;/p&gt;

&lt;h1 id=&quot;发音过程&quot;&gt;发音过程&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;气流 airstream: 从肺部出来；&lt;/li&gt;
  &lt;li&gt;发声 phonation: 喉部（声带）决定清音和浊音；&lt;/li&gt;
  &lt;li&gt;口鼻 oro-nasal: 气流进入口腔还是鼻腔，形成鼻音和口腔音；&lt;/li&gt;
  &lt;li&gt;发音 articulation: 通过舌的运动改变口腔的形状，发出各种不同的口腔音。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;结合这四个步骤，我们可以对发音进行不同的分类。&lt;/p&gt;

&lt;h1 id=&quot;vowel-vs-consonant&quot;&gt;&lt;a href=&quot;/assets/phonetics_intro.pdf&quot;&gt;Vowel vs. Consonant&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;语音一般分为辅音 (consonant) 和元音 (vowel) 两大类，元音和辅音的根本区别在于气流是否受阻。注意是“受阻”不是“完全没有”。发辅音时，声道紧闭或声道变窄使气流无法排出，或排出时会产生能够辨别出的摩擦。发元音时气流可以相对不受阻碍地从口腔或鼻腔中排出而不会产生类似的现象。&lt;/p&gt;

&lt;p&gt;A vowel is a sound such as the ones represented in writing by the letters &apos;a&apos;, &apos;e&apos; &apos;i&apos;, &apos;o&apos; and &apos;u&apos;, which you pronounce with your mouth open, allowing the air to flow through it.&lt;/p&gt;

&lt;p&gt;A consonant is a sound such as &apos;p&apos;, &apos;f&apos;, &apos;n&apos;, or &apos;t&apos; which you pronounce by &lt;em&gt;stopping&lt;/em&gt; the air flowing freely through your mouth.&lt;/p&gt;

&lt;p&gt;因此，在描述辅音音姿的时候，特别需要考虑的是气流在口腔中受阻的位置和方式，而描述元音时，需要考虑的主要是舌在口腔中的位置。&lt;/p&gt;

&lt;p&gt;从理论上讲,一个音段要么是元音，要么就是辅音。但像 yet 中的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[j]&lt;/code&gt; 和 wet 中的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[w]&lt;/code&gt; 实际上是完完全全的元音，只是它们出现在辅音的位置上。我们一般用术语“半元音 (semi-vowel)”来描述这些既非元音又非辅音，而是处于中间状态的语音。&lt;/p&gt;

&lt;p&gt;We can also divide phonation into voiceless (清音：声带不颤动) and voiced （浊音：声带颤动）。对应的我们有“清辅音”和“浊辅音”。对于元音，所有的都是“浊元音”。我们还可以根据是否“送气（aspirated)”来区分发音，如在 peak 中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/p/&lt;/code&gt; 送气，用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[pͪ]&lt;/code&gt; 表示，在 speak 中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/p/&lt;/code&gt; 不送气，用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[p]&lt;/code&gt; 表示。peak 的严式注音为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[pͪik]&lt;/code&gt;, 宽式注音为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[pik]&lt;/code&gt;, 严式注音包括了对送气现象的表述。&lt;/p&gt;

&lt;h1 id=&quot;长短元音符号&quot;&gt;长短元音符号&lt;/h1&gt;

&lt;p&gt;英语词 fit 和 feet 中间的元音是用长度符号 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ː]&lt;/code&gt; 来区分的（即 fit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[fit]&lt;/code&gt;, feet &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[fiːt]&lt;/code&gt;），表示为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[iː, i; uː, u; ɔː, ɔ; ɜː, ɜ]&lt;/code&gt;. 现在有了独立的短音符号 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[i, ɪ; u, ʊ; ɔ, ɒ; ɜ, ə]&lt;/code&gt;，每一对的前者是短音，后者是长音。有字典为了便于区别，同时标注长度符号和新短音符号 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[iː, ɪ; uː, ʊ; ɔː, ɒ; ɜː, ə]&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;syllable-音节&quot;&gt;Syllable 音节&lt;/h1&gt;

&lt;p&gt;元音和辅音都是指的单个发音，称为“音段（segment）”，当音段组合成音节（syllable）。通常把音节分成两个部分：韵基（rime）和节首（onset）, 韵基中的元音是节核（nucleus）, 后面的辅音称作节尾（coda）。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/eng_syllable.png&quot; alt=&quot;eng syllable&quot; /&gt;&lt;/p&gt;

&lt;p&gt;所有音节必须有节核,但不是所有的音节都有节首和节尾。没有节尾的音节叫做“开音节（open syllable）”, 有节尾的音节叫做“闭音节（closed syllable）”。&lt;/p&gt;

&lt;p&gt;在词的层面上，一个词在单独提及的时候（即单词本身没有在句子里）称为“引用形式（citation form）”，这时至少有一个音节是重读的。也就是说，如果某个词是单音节词，那么这个词的引用形式必须是重读的，如不定冠词 a，单独说这个词的时候应该说 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[eɪ]&lt;/code&gt;，而不是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ə]&lt;/code&gt;. 虚词一般都有重读和轻读两种形式,在短语和句子的层面上一般采取轻读。&lt;/p&gt;

&lt;p&gt;在多音节的词中,至少有一个音节是重读音节。在比较长的词中（一般指 4 个音节以上）,还会有两个重读音节。&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Bitcoin</title>
   <link href="/2018/05/22/bitcoin/"/>
   <updated>2018-05-22T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/05/22/bitcoin</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#bitcoin-core-installation&quot; id=&quot;markdown-toc-bitcoin-core-installation&quot;&gt;Bitcoin Core Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#mode&quot; id=&quot;markdown-toc-mode&quot;&gt;Mode&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configuration&quot; id=&quot;markdown-toc-configuration&quot;&gt;Configuration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#daemonserver&quot; id=&quot;markdown-toc-daemonserver&quot;&gt;Daemon/server&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#rpc&quot; id=&quot;markdown-toc-rpc&quot;&gt;RPC&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#testing&quot; id=&quot;markdown-toc-testing&quot;&gt;Testing&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#info&quot; id=&quot;markdown-toc-info&quot;&gt;Info&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#block&quot; id=&quot;markdown-toc-block&quot;&gt;Block&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mining&quot; id=&quot;markdown-toc-mining&quot;&gt;Mining&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#peer&quot; id=&quot;markdown-toc-peer&quot;&gt;Peer&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#transaction&quot; id=&quot;markdown-toc-transaction&quot;&gt;Transaction&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#examine-transaction&quot; id=&quot;markdown-toc-examine-transaction&quot;&gt;Examine transaction&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#confirm-a-transaction&quot; id=&quot;markdown-toc-confirm-a-transaction&quot;&gt;Confirm a transaction&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#stop-daemon&quot; id=&quot;markdown-toc-stop-daemon&quot;&gt;Stop daemon&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This post only focuses only on Bitcoin daemon deployment on Linux. To get Bitcoin outline, concepts, principles, read NextCloud Note.&lt;/p&gt;

&lt;h1 id=&quot;bitcoin-core-installation&quot;&gt;Bitcoin Core Installation&lt;/h1&gt;

&lt;p&gt;I choose to install daemon instead of QT GUI.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ / emerge &lt;span class=&quot;nt&quot;&gt;-avt&lt;/span&gt; net-p2p/bitcoind net-p2p/bitcoin-cli
root@tux ~ / less /etc/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;bitcoin/bitcoin.conf,init.d/bitcoind,conf.d/bitcoind&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;mode&quot;&gt;Mode&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Full node (mainnet)&lt;/p&gt;

    &lt;p&gt;A full node is a program that fully validates transactions and blocks. Running in full node comes with certain costs (i.e. harward requirements). To store the full blockchain, you need around 145 gigabytes of disk space, 2 gigabytes of RAM, broadband Internet etc.&lt;/p&gt;

    &lt;p&gt;Mostly, you should keep your computer running at least 6 hours continuously without interruption.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Prune mode (mainnet)&lt;/p&gt;

    &lt;p&gt;Prune mode save diskpace by parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--prune=&amp;lt;n&amp;gt;&lt;/code&gt; which prunes (delete) old blocks. By default, 0 disables pruning blocks; 1 allows manual pruning via RPC; &amp;gt;550 = automatically prune block files to stay under the specified target size in MiB.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://en.bitcoin.it/wiki/Testnet&quot;&gt;Testnet&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Unlike mainnet, the testnet is an alternative blockchain, only to be used to testing. Coins in testnet are separate and distinct from actual bitcoins, and are never supposed to have any value.&lt;/p&gt;

    &lt;p&gt;This allows application developers or bitcoin testers to experiment, without having to use real bitcoins or worrying about breaking the main bitcoin chain. What is more, a raw recruit can play around with testnet and switch to real Bitcoin blockchain afterwards.&lt;/p&gt;

    &lt;p&gt;The size of testnet blockchain is not trivial. As of January 2018, it is was 14GB, containing data for about 6 years worth of testnet activity.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;We can combine Testnet and Prune together.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://bitcoin.org/en/developer-examples#regtest-mode&quot;&gt;Regression Test Mode (Regtest)&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;To further simplify the testing process, we can use &lt;em&gt;local&lt;/em&gt; Regtest mode, where interaction with random peers and blocks is unnecessary or unwanted. It lets you instantly create a brand-new &lt;em&gt;private&lt;/em&gt; block chain with the same basic rules as testnet — but one major difference: you choose when to create new blocks, so you have complete control over the environment. Unlike previous modes, block generation is pretty fast!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;configuration&quot;&gt;&lt;a href=&quot;https://github.com/bitcoin/bitcoin/blob/master/contrib/debian/examples/bitcoin.conf&quot;&gt;Configuration&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;Default ports as of 0.16.0:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;mainnet&lt;/th&gt;
      &lt;th&gt;testnet&lt;/th&gt;
      &lt;th&gt;regtest&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;P2p&lt;/td&gt;
      &lt;td&gt;8333&lt;/td&gt;
      &lt;td&gt;18333&lt;/td&gt;
      &lt;td&gt;18444&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;RPC&lt;/td&gt;
      &lt;td&gt;8332&lt;/td&gt;
      &lt;td&gt;18332&lt;/td&gt;
      &lt;td&gt;18443&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Here is a configration for Regtest mode:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/bitcoin/bitcoin.conf

#
# Mode
#

regtest=1
#testnet=1

#
# Network
#

#proxy=127.0.0.1:1080

#listen=1

#https://github.com/bitcoin/bitcoin/blob/master/doc/tor.md
#onion=127.0.0.1:9050
listenonion=0

bind=127.0.0.1
bind=192.168.56.100
#port=18444

addnode=192.168.56.101
#addnode=192.168.56.101:18444

#connect=192.168.56.101
#connect=192.168.56.101:18444

#
# RPC
#

server=1

#https://github.com/bitcoin/bitcoin/tree/master/share/rpcauth
rpcauth=myuser:ff164b6f16a012debdadc24e7f7da$eb5427acefdcf06e0cf4f070568297e93a29bd0e16f28bac6a6c9dce5a0d08fa
#rpcuser=myuser
#rpcpassword=AbfGbK7qUbpLh3lLtgMKD3xKFUupXgC3BSsf98X2jrI=

rpcallowip=127.0.0.1
rpcallowip=::1
rpcallowip=192.168.0.0/24
rpcbind=127.0.0.1
#rpcport=18443

#
# Miscellanous
#

#prune=550
txindex=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;prune&lt;/em&gt; and &lt;em&gt;txindex&lt;/em&gt; are incompatible. Turn on &lt;em&gt;prune&lt;/em&gt; in &lt;em&gt;mainnet&lt;/em&gt; to save disk space.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;rpcauth&lt;/em&gt; is recommended over &lt;em&gt;rpcuser/rpcpassword&lt;/em&gt;. It generates random password if we do not offer one.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# /path/to/rpcauth.py &amp;lt;username&amp;gt; [&amp;lt;password&amp;gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;rpcauth&lt;/em&gt; is only used by server side. Please write down generated &lt;em&gt;rpcpassword&lt;/em&gt; pair as it will be used by client side.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://bitcoin.stackexchange.com/a/10766&quot;&gt;Difference&lt;/a&gt; between &lt;em&gt;addnode&lt;/em&gt; and &lt;em&gt;connect&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;addnode&lt;/em&gt; adds a node to the list of nodes to connect while &lt;em&gt;connect&lt;/em&gt; only connects to this very node, ignoring other nodes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;connect=&lt;/em&gt; and &lt;em&gt;proxy=&lt;/em&gt; will disable &lt;em&gt;listen=1&lt;/em&gt;, rejecting incoming connections.&lt;/li&gt;
  &lt;li&gt;We can connect the Bitcoin network through Tor. A bit further, we set local &lt;em&gt;.onion&lt;/em&gt; address so that our own Bitcoin node is reachable through Tor.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;daemonserver&quot;&gt;Daemon/server&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ / rc-service bitcoind start
root@tux ~ / ss &lt;span class=&quot;nt&quot;&gt;-npelt&lt;/span&gt;
root@tux ~ / ll /var/lib/bitcoin/.bitcoin/
root@tux ~ / gpasswd &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; username bitcoin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Bitcoin is running in daemon mode in the background.&lt;/li&gt;
  &lt;li&gt;We should add username to bitcoin group, otherwise &lt;em&gt;bitcoin_cli&lt;/em&gt; cannot run with username account.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;From &lt;em&gt;/etc/init.d/bitcoind&lt;/em&gt; we find critical parameters are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-conf&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-datadir&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;Usually, we put &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-conf&lt;/code&gt; under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-datadir&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Bitcoin-qt disables &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-server&lt;/code&gt; by default and we can access to RPC through &lt;em&gt;Help -&amp;gt; Debug window -&amp;gt; Console&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;rpc&quot;&gt;&lt;a href=&quot;https://bitcoin.org/en/developer-reference#remote-procedure-calls-rpcs&quot;&gt;RPC&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;Unlike the server side, client side &lt;a href=&quot;https://bitcoin.org/en/developer-reference#rpc-quick-reference&quot;&gt;bitcoin_cli&lt;/a&gt; does not recognize &lt;em&gt;rpcauth&lt;/em&gt;. To authenticate itself, &lt;em&gt;bitcoin_cli&lt;/em&gt; read &lt;em&gt;rpcpassword&lt;/em&gt; from configuration file or command line option.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# enable bitcoin group without re-login.&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# newgrp - bitcoin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We could tell it to share configuration with server:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli -conf=/etc/bitcoin/bitcoin.conf [-rpcuser=user -rpcpassword=password] help&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# generate bitcoin.conf symlink&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# mkdir -p ~/.bitcoin; ln -sv /etc/bitcoin/bitcoin.conf ~/.bitcoin/bitcoin.conf&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli [-rpcuser=user -rpcpassword=password] help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, we set separate client configration file without symlink. You are recommended to use this method:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ~/.bitcoin/bitcoin.conf

regtest=1
rpcuser=myuser
rpcpassword=mypassword
#rpcport=18443
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For client options, check man page.&lt;/p&gt;

&lt;h1 id=&quot;testing&quot;&gt;&lt;a href=&quot;https://bitcoin.org/en/developer-documentation&quot;&gt;Testing&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;In this section, I will discuss more Bitcoin details with Regtest mode.&lt;/p&gt;

&lt;h2 id=&quot;info&quot;&gt;Info&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli help&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli help getblockchaininfo&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli getblockchaininfo | getwalletinfo | getnetworkinfo | getpeerinfo&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli logging &quot;[\&quot;all\&quot;]&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;block&quot;&gt;Block&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli getblockhash 50&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli getblock &amp;lt;returned hash&amp;gt; [0 | 1 | 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To examine a block information, we should first get its hash value. To get the block hash, we use &lt;em&gt;height&lt;/em&gt; vlue which means distance from the &lt;em&gt;genesis&lt;/em&gt; block.&lt;/p&gt;

&lt;h2 id=&quot;mining&quot;&gt;Mining&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mining is just generating in Regtest mode.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli generate 101&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli getbalance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A Regtest blockchain with 101 blocks is created, which takes less than a second. Each confirmed block reward is 50 bitcoins (no transaction fees). However, a block &lt;a href=&quot;https://en.bitcoin.it/wiki/Confirmation&quot;&gt;must have 100 confirmations&lt;/a&gt; before that reward can be spent, so we generate 101 blocks to get access to the coinbase transaction from block 1.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli generate 1&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli getbalance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;peer&quot;&gt;&lt;a href=&quot;https://bitcoin.stackexchange.com/a/36014&quot;&gt;Peer&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Thgough we use Regest locally, connecting to peer is necessary when you want to test transactions. To do this, we just file run another Regtest instance locally with different &lt;em&gt;port&lt;/em&gt;, &lt;em&gt;conf&lt;/em&gt; and &lt;em&gt;datadir&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you&apos;d like, the extra Regtest instance could be moved into virtual machine as long as Hostonly network is correctly configured. Please be noted that, launch virtual machine before host Regtest instance which otherwise does not know about Hostonly interface IP.&lt;/p&gt;

&lt;p&gt;In order that two nodes notice each other, we should use parameter &lt;em&gt;addnode/connect&lt;/em&gt; or command line option thereof.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli getaddednodeinfo | getpeerinfo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;transaction&quot;&gt;Transaction&lt;/h2&gt;

&lt;p&gt;Once we have established connection to peers, we can send bitcoins around. Fristly, we should generate a new address to receive payments.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli getnewaddress&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli listreceivedbyaddress 1 true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Send 10 bitcoins to the address using &lt;em&gt;sendtoaddress&lt;/em&gt; RPC command which automatically selects an unspent transaction output (UTXO) from which to spend the satoshis. To check UTXO, we use &lt;em&gt;listunspent&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli getbalance&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli listunspent&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli sendtoaddress $NEW_ADDRESS 10.00 &quot;first spending&quot; &quot;send to myself&quot; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;examine-transaction&quot;&gt;Examine transaction&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli gettransaction &amp;lt;transaction hash returned&amp;gt; true&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli getrawtransaction &amp;lt;transaction hash returned&amp;gt; true&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli decoderawtransaction &amp;lt;hex string returned&amp;gt;&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli listunspent 0&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli listreceivedbyaddress 1 true&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli listtransactions &quot;&quot; 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;confirm-a-transaction&quot;&gt;Confirm a transaction&lt;/h3&gt;

&lt;p&gt;Up to now, the transaction is not yet confirmed! We should mine 100 blocks to confirm it.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli generate 100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;If the input is from coinbase transaction, you can&apos;t spent it until it get 100 confirmations, avoiding &lt;a href=&quot;https://bitcoin.org/en/glossary/fork&quot;&gt;blockchain fork&lt;/a&gt; issue. Hence, 1 confirmation is not enough!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Similary, we can send bitcoins the other Regtest node.&lt;/p&gt;

&lt;h2 id=&quot;stop-daemon&quot;&gt;Stop daemon&lt;/h2&gt;

&lt;p&gt;We can stop the daemon:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# bitcoin-cli stop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;However, we&apos;d better use OpenRC or Systemd service.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>Docker Newbie</title>
   <link href="/2018/04/21/docker-newbie/"/>
   <updated>2018-04-21T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/04/21/docker-newbie</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#architecture&quot; id=&quot;markdown-toc-architecture&quot;&gt;Architecture&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#docker-engine&quot; id=&quot;markdown-toc-docker-engine&quot;&gt;Docker Engine&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#docker-desktop&quot; id=&quot;markdown-toc-docker-desktop&quot;&gt;Docker Desktop&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#image-container-and-registry&quot; id=&quot;markdown-toc-image-container-and-registry&quot;&gt;Image Container and Registry&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#start-daemon&quot; id=&quot;markdown-toc-start-daemon&quot;&gt;Start daemon&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#dockersock&quot; id=&quot;markdown-toc-dockersock&quot;&gt;docker.sock&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#docker-context&quot; id=&quot;markdown-toc-docker-context&quot;&gt;Docker Context&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cli-sample&quot; id=&quot;markdown-toc-cli-sample&quot;&gt;CLI Sample&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pull-image&quot; id=&quot;markdown-toc-pull-image&quot;&gt;Pull Image&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#launch-containers&quot; id=&quot;markdown-toc-launch-containers&quot;&gt;Launch Containers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#runtime-metrics&quot; id=&quot;markdown-toc-runtime-metrics&quot;&gt;Runtime metrics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#data-share&quot; id=&quot;markdown-toc-data-share&quot;&gt;Data Share&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#env-variables&quot; id=&quot;markdown-toc-env-variables&quot;&gt;ENV Variables&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#selinux&quot; id=&quot;markdown-toc-selinux&quot;&gt;SELinux&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#nginx-container-sample&quot; id=&quot;markdown-toc-nginx-container-sample&quot;&gt;Nginx Container Sample&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#get-into-container&quot; id=&quot;markdown-toc-get-into-container&quot;&gt;Get into Container&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#networking-drivers&quot; id=&quot;markdown-toc-networking-drivers&quot;&gt;Networking Drivers&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#dns&quot; id=&quot;markdown-toc-dns&quot;&gt;DNS&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#hostdockerinternal&quot; id=&quot;markdown-toc-hostdockerinternal&quot;&gt;host.docker.internal&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#self-define-network&quot; id=&quot;markdown-toc-self-define-network&quot;&gt;Self-define Network&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ssh-agent-forwarding&quot; id=&quot;markdown-toc-ssh-agent-forwarding&quot;&gt;SSH Agent Forwarding&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#link&quot; id=&quot;markdown-toc-link&quot;&gt;link&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#exec-and-shell&quot; id=&quot;markdown-toc-exec-and-shell&quot;&gt;exec and shell&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#custom-image&quot; id=&quot;markdown-toc-custom-image&quot;&gt;Custom Image&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#docker-commit&quot; id=&quot;markdown-toc-docker-commit&quot;&gt;Docker Commit&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#docker-build-dockerfile&quot; id=&quot;markdown-toc-docker-build-dockerfile&quot;&gt;Docker Build Dockerfile&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#share-images&quot; id=&quot;markdown-toc-share-images&quot;&gt;Share Images&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#docker-compose&quot; id=&quot;markdown-toc-docker-compose&quot;&gt;Docker Compose&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#troubleshooting&quot; id=&quot;markdown-toc-troubleshooting&quot;&gt;Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;architecture&quot;&gt;Architecture&lt;/h1&gt;

&lt;p&gt;In general, &lt;a href=&quot;https://docs.docker.com/get-started/docker-overview/#docker-architecture&quot;&gt;Docker works in client-server mode&lt;/a&gt; illustrated in the figure below.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/docker-architecture.png&quot; alt=&quot;docker-architecture.png&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Server-side &lt;a href=&quot;#docker-engine&quot;&gt;Docker Engine&lt;/a&gt;, also called Docker Daemon, is the &lt;em&gt;dockerd&lt;/em&gt; that manages the containers, images, volumes, networks, etc.&lt;/p&gt;

    &lt;p&gt;The daemon serves requests by RESTful API &lt;a href=&quot;#dockersock&quot;&gt;over local Unix socket&lt;/a&gt; or &lt;a href=&quot;https://docs.docker.com/engine/daemon/remote-access/&quot;&gt;over remote network interface&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Client-sdie Docker CLI are &lt;em&gt;docker&lt;/em&gt;, &lt;em&gt;docker-compose&lt;/em&gt;, etc.&lt;/p&gt;

    &lt;p&gt;CLI options and arguments are consolidated and transformed to REST API. We can &lt;a href=&quot;#dockersock&quot;&gt;use cURL to manage Docker objects&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The term &quot;Docker&quot; most of the time means the overall architecture.&lt;/p&gt;

&lt;h2 id=&quot;docker-engine&quot;&gt;Docker Engine&lt;/h2&gt;

&lt;p&gt;Most of the time, Docker Daemon is merely the daemon part. But occasionally, it may refer to the collection of Docker daemon, the Docker REST API and the Docker client. In this section, we focus on the daemon.&lt;/p&gt;

&lt;p&gt;Docker Engine relies on Linux kernel under the hood, like the &lt;a href=&quot;https://man7.org/linux/man-pages/man7/namespaces.7.html&quot;&gt;namespace&lt;/a&gt; (containers isolation), &lt;a href=&quot;https://man7.org/linux/man-pages/man7/cgroups.7.html&quot;&gt;cgroup&lt;/a&gt; (resources management), libraries, etc. So, by &quot;container&quot;, we actually mean &quot;Linux container&quot;. But for convenience, we just call it &quot;container&quot;.&lt;/p&gt;

&lt;p&gt;At the very beginning, Docker Engine is an integrated piece of daemon including all capabilities to manage containers, images, volumes, networks, etc.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+--------------+            +-----------------+        +----------+   
|              | REST API   |  Docker Engine  |        |+----------+  
|  docker CLI  +-----------&amp;gt;|                 +-------&amp;gt;+|+----------+ 
|              |            |     dockerd     |         +|+----------+
+--------------+            +-----------------+          +|container+|
                                                          +----------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Later on (2017), in order to expand its adoption and add neutrality and modularity, the core capabilities are donated to CNCF as a seperate daemon &lt;a href=&quot;https://www.docker.com/blog/containerd-vs-docker/&quot;&gt;containerd&lt;/a&gt; (i.e. &lt;em&gt;docker-containerd&lt;/em&gt;). The Docker Engine only focuses on developer experience like serving login, build, inspect, log, etc.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                                                       +--------------+
+--------------+            +-----------------+        |              |       +----------+
|              | REST API   |  Docker Engine  |  gRPC  | containerd   |       |+----------+
|  docker CLI  +-----------&amp;gt;|                 +-------&amp;gt;|     +------+ +------&amp;gt;+|+----------+ 
|              |            |     dockerd     |        |     | runc | |        +|+----------+
+--------------+            +-----------------+        |     +------+ |         +|container+|
                                                       +--------------+          +----------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the meantime, the &lt;a href=&quot;https://opencontainers.org/&quot;&gt;Open Container Initiative (OCI)&lt;/a&gt; standardizes the &lt;em&gt;containerd&lt;/em&gt;. According to the standard, the responsibility of creating containers was removed from &lt;em&gt;containerd&lt;/em&gt; in faviour of &lt;em&gt;runtime&lt;/em&gt; (e.g. &lt;em&gt;runc&lt;/em&gt;). The interaction with Linux namespace and Linux cgroup has shifted from &lt;em&gt;containerd&lt;/em&gt; to &lt;em&gt;runtime&lt;/em&gt;. We call &lt;em&gt;containerd&lt;/em&gt; the high-level runtime, managing container lifecycle, images, volumes, network, etc.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                                                       +--------------+
+--------------+            +-----------------+        |              |       +----------+
|              | REST API   |  Docker Engine  |  gRPC  | containerd   |       |+----------+
|  docker CLI  +-----------&amp;gt;|                 +-------&amp;gt;|     +------+ +------&amp;gt;+|+----------+ 
|              |            |     dockerd     |        |     | runc | |        +|+----------+
+--------------+            +-----------------+        |     +------+ |         +|container+|
                                                       +--------------+          +----------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With OCI, everyone can build his own containerization system. Nowadays, there exist &lt;a href=&quot;https://docs.docker.com/engine/daemon/alternative-runtimes/&quot;&gt;multiple OCI runtimes&lt;/a&gt;. In order to support those runtimes, Docker inserts a new component between &lt;em&gt;containerd&lt;/em&gt; and &lt;em&gt;runtime&lt;/em&gt;, namely the &lt;a href=&quot;https://docs.docker.com/engine/daemon/alternative-runtimes/&quot;&gt;containerd-shim&lt;/a&gt; (e.g. &lt;em&gt;docker-containerd-shim&lt;/em&gt;). The &lt;em&gt;containerd-shim&lt;/em&gt; invokes the &lt;em&gt;runtime&lt;/em&gt; (e.g. &lt;em&gt;runc&lt;/em&gt;) to create the container. Once the container is created, the &lt;em&gt;runtime&lt;/em&gt; exits and the lifecycle management is handed over to &lt;em&gt;containerd&lt;/em&gt; and &lt;em&gt;container-shim&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Some of the runtimes are fully compatibile with &lt;em&gt;docker-containerd-shim&lt;/em&gt; like the &lt;a href=&quot;https://github.com/youki-dev/youki&quot;&gt;youki&lt;/a&gt;, while others are not like the &lt;a href=&quot;https://wasmtime.dev/&quot;&gt;Wasmtime&lt;/a&gt;. Runtimes compatibile with &lt;em&gt;docker-containerd-shim&lt;/em&gt; can be a drop-in replacement for &lt;em&gt;runc&lt;/em&gt;. Runtimes incompatibile with &lt;em&gt;docker-containerd-shim&lt;/em&gt; must implements their own &lt;em&gt;shim&lt;/em&gt; according to &lt;a href=&quot;https://github.com/containerd/containerd/blob/main/core/runtime/v2/README.md&quot;&gt;shim API&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                                                                                                   container lifecycle
                                                                                   +--------------------------------------------+
                                                                                   |                                            v
                                                                                   |                   +---------------+   +---------+
                                                                                   |                   | runtime youki +--&amp;gt;|container|
                                                                                   |                   |    (exit)     |   +---------+
                                                                                   |                   +---------------+
                                                                                   v                      ^
+--------------+            +-----------------+        +--------------+    +-----------------+            |
|              |  REST API  |  Docker Engine  |  gRPC  |  High-level  |    |                 |   image    |                     .
|  docker CLI  +-----------&amp;gt;|                 +-------&amp;gt;|   runtime    +---&amp;gt;| containerd-shim +------------+                     .
|              |            |     dockerd     |        |  containerd  |    |                 |   bundle   |                     .
+--------------+            +-----------------+        +--------------+    +-----------------+            |
                                                                                   ^                      v
                                                                                   |                   +--------------+
                                                                                   |                   | runtime runc |    +---------+
                                                                                   |                   |    (exit)    +---&amp;gt;|container|
                                                                                   |                   +--------------+    +---------+
                                                                                   |                                            ^
                                                                                   +--------------------------------------------+
                                                                                                   container lifecycle
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;More and more middle layers are added to the architecture, making it too complicated. &lt;a href=&quot;https://podman.io/&quot;&gt;podman&lt;/a&gt;, on the other hand, is much more simpler as follows. &lt;em&gt;podman&lt;/em&gt; talks directly to the runtime, without &lt;em&gt;dockerd&lt;/em&gt;, &lt;em&gt;conainerd&lt;/em&gt; or &lt;em&gt;containerd-shim&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;podman CLI -&amp;gt; runtime runc -&amp;gt; containers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can actually create and run containers directly with &lt;em&gt;runtime runc&lt;/em&gt;. It is out of the scope of this post, please read &lt;a href=&quot;https://github.com/opencontainers/runc&quot;&gt;official runc page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You are strongly recommended to read &lt;a href=&quot;https://stackoverflow.com/q/46649592/2336707&quot;&gt;https://stackoverflow.com/q/46649592/2336707&lt;/a&gt;. The following output is a demonstration in my dev environment. Two containers were created and they are the child processes of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;containerd-shim-runc-v2&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; httpbin &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; kennethreitz/httpbin
4bd1077052750a2a7552e4347bcbba483d47f2555b89874606c0b04b93f7c2dc

ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-itd&lt;/span&gt; ubuntu
18be920d5a998ceee5f438ae43c7d1171fec6d34d4742c66611ff7a63f9d6a68

ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS          PORTS                                       NAMES
a598c760b207   ubuntu                 &lt;span class=&quot;s2&quot;&gt;&quot;/bin/bash&quot;&lt;/span&gt;              29 minutes ago   Up 29 minutes                                               ubuntu
4bd107705275   kennethreitz/httpbin   &lt;span class=&quot;s2&quot;&gt;&quot;gunicorn -b 0.0.0.0…&quot;&lt;/span&gt;   48 minutes ago   Up 48 minutes   0.0.0.0:32768-&amp;gt;80/tcp, &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;::]:32768-&amp;gt;80/tcp   httpbin

ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps  &lt;span class=&quot;nt&quot;&gt;-eF&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--forest&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# dockerd&lt;/span&gt;
root         530       1  0 570701 82248  3 Dec23 ?        00:00:29 /usr/bin/dockerd &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; fd:// &lt;span class=&quot;nt&quot;&gt;--containerd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/run/containerd/containerd.sock
root       15033     530  0 436282 3968   0 Dec27 ?        00:00:00  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /usr/bin/docker-proxy &lt;span class=&quot;nt&quot;&gt;-proto&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-host-ip&lt;/span&gt; 0.0.0.0 &lt;span class=&quot;nt&quot;&gt;-host-port&lt;/span&gt; 32768 &lt;span class=&quot;nt&quot;&gt;-container-ip&lt;/span&gt; 172.17.0.2 &lt;span class=&quot;nt&quot;&gt;-container-port&lt;/span&gt; 80
root       15040     530  0 399416 3840   0 Dec27 ?        00:00:00  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /usr/bin/docker-proxy &lt;span class=&quot;nt&quot;&gt;-proto&lt;/span&gt; tcp &lt;span class=&quot;nt&quot;&gt;-host-ip&lt;/span&gt; :: &lt;span class=&quot;nt&quot;&gt;-host-port&lt;/span&gt; 32768 &lt;span class=&quot;nt&quot;&gt;-container-ip&lt;/span&gt; 172.17.0.2 &lt;span class=&quot;nt&quot;&gt;-container-port&lt;/span&gt; 80
&lt;span class=&quot;c&quot;&gt;# containerd&lt;/span&gt;
root         357       1  0 468968 48524  3 Dec23 ?        00:02:22 /usr/bin/containerd
&lt;span class=&quot;c&quot;&gt;# container httpbin&lt;/span&gt;
root       15063       1  0 309542 13748  0 Dec27 ?        00:00:04 /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; 4bd1077052750a2a7552e4347bcbba483d47f2555b89874606c0b04b93f7c2dc &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
root       15083   15063  0 21495 24480   0 Dec27 ?        00:00:05  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /usr/bin/python3 /usr/local/bin/gunicorn &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 0.0.0.0:80 httpbin:app &lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt; gevent
root       15109   15083  0 32493 33912   3 Dec27 ?        00:00:08      &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /usr/bin/python3 /usr/local/bin/gunicorn &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 0.0.0.0:80 httpbin:app &lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt; gevent
&lt;span class=&quot;c&quot;&gt;# container ubuntu&lt;/span&gt;
root       15363       1  0 309542 13780  3 Dec27 ?        00:00:04 /usr/bin/containerd-shim-runc-v2 &lt;span class=&quot;nt&quot;&gt;-namespace&lt;/span&gt; moby &lt;span class=&quot;nt&quot;&gt;-id&lt;/span&gt; a598c760b2071f4951d35d255d3669ce3e9877534b36efcd21e2dfcb8727b136 &lt;span class=&quot;nt&quot;&gt;-address&lt;/span&gt; /run/containerd/containerd.sock
root       15383   15363  0  1147  3840   2 Dec27 pts/0    00:00:00  &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt; /bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;docker-desktop&quot;&gt;Docker Desktop&lt;/h3&gt;

&lt;p&gt;In order to run containers on Window and macOS, a Linux virtual machine is required to host &lt;em&gt;dockerd&lt;/em&gt;, &lt;em&gt;containerd&lt;/em&gt;, &lt;em&gt;containerd-shim&lt;/em&gt;, &lt;em&gt;runtime&lt;/em&gt;, etc. The Docker CLI remains on the host.&lt;/p&gt;

&lt;p&gt;As such, Docker provides the Docker Desktop. Docker Desktop is an &lt;a href=&quot;https://docs.docker.com/desktop/&quot;&gt;all-in-one&lt;/a&gt; (including GUI) software and gives us a uniform expiernce accross Linux, Window and macOS.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/docker-desktop.png&quot; alt=&quot;docker-desktop.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Especially, Docker Desktop creates the Linux virtual machine for us, so that we are not bothered on this. On Window and macOS, Docker Desktop utilizes native virtualization framework (Hyper-V and WSL 2 of Windows; Hypervisor of macOS) to boost performance. On Linux system, Docker Desktop is not a must. However, if we choose it, the Virtual Machine is still created.&lt;/p&gt;

&lt;h1 id=&quot;image-container-and-registry&quot;&gt;Image Container and Registry&lt;/h1&gt;

&lt;p&gt;Dockers comprises &lt;em&gt;image&lt;/em&gt;, &lt;em&gt;container&lt;/em&gt; and &lt;em&gt;registry&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Image is &lt;em&gt;static&lt;/em&gt;, &lt;em&gt;readonly&lt;/em&gt; and a &lt;em&gt;minimal&lt;/em&gt; root filesystem &lt;a href=&quot;#share-image&quot;&gt;bundle&lt;/a&gt;. There are many highly qualified base iamge from official registry like &lt;em&gt;nginx&lt;/em&gt;, &lt;em&gt;redis&lt;/em&gt;, &lt;em&gt;php&lt;/em&gt;, &lt;em&gt;python&lt;/em&gt;, &lt;em&gt;ruby&lt;/em&gt; etc. Especially, we have &lt;em&gt;ubuntu&lt;/em&gt;, &lt;em&gt;centos&lt;/em&gt;, etc. that are just OS minimal bare bones (like Gentoo stage tarball).&lt;/p&gt;

    &lt;p&gt;An image consists of multiple incremental layers that are defined by a &lt;a href=&quot;#docker-build-dockerfile&quot;&gt;Dockerfile&lt;/a&gt;. Correspondingly, we call the image storage &lt;a href=&quot;https://docs.docker.com/storage/storagedriver/&quot;&gt;layer storage&lt;/a&gt; based on Union Filesytem (FS). Recall that booting USB stick also uses Union FS. The most adopted Union FS are &lt;em&gt;overlay2&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Container is a set of processes with added isolation (Linux namespace) and resource management (Linux cgroup).&lt;/p&gt;

    &lt;p&gt;It is created on top of a base image with an additional layer storing &lt;em&gt;running&lt;/em&gt; but volatile data. We can think of image and container as class and object in Object-oriented programming.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Registry is &lt;em&gt;store&lt;/em&gt; where users publicize, share and download &lt;em&gt;repostitory&lt;/em&gt;. The default registry is &lt;em&gt;docker.io&lt;/em&gt; or &lt;em&gt;registry-1.docker.io&lt;/em&gt; with a frontend website &lt;a href=&quot;https://hub.docker.com&quot;&gt;Docker Hub&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Repository, on the other hand, actually refers to &lt;em&gt;name&lt;/em&gt; of an image (e.g. &lt;em&gt;ubuntu&lt;/em&gt;). We can specify &lt;em&gt;version&lt;/em&gt; of a repository by a &lt;em&gt;tag&lt;/em&gt; (label) like &lt;em&gt;ubuntu:16.04&lt;/em&gt; (colon separator). The default tag is &lt;em&gt;latest&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href=&quot;https://docs.docker.com/reference/cli/docker/image/tag/#description&quot;&gt;naming of an image&lt;/a&gt; follows the format as follows.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;registry.fqdn[:port]/[namespace/]repository[:tag | @&amp;lt;image-ID&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Default registry can be ommitted. Others like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quay.io&lt;/code&gt; must be provided.&lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;namespace&lt;/em&gt; part means a registered account in the registry. It can be an individual user name or an organization name like &quot;kong&quot;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;repository&lt;/em&gt; is the default &lt;em&gt;name&lt;/em&gt; of an image like &quot;ubuntu&quot; and &quot;kong-gateway&quot;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;tag&lt;/em&gt; is a string. Default to &lt;em&gt;latest&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;image id&lt;/em&gt; comprises a SHA256 &lt;em&gt;digest&lt;/em&gt; like &lt;em&gt;@sha256:abea36737d98dea6109e1e292e0b9e443f59864b&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Specifying an image by tag can always gets the latest updates. For example, every time a patch release is released (e.g. &lt;em&gt;kong/kong:3.4.5&lt;/em&gt;), &lt;em&gt;kong/kong:3.4&lt;/em&gt; refers to that patch version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.4.5&lt;/code&gt; with a different digest. On the other hand, an image specified by digest always is pinned to that specific image. See &lt;a href=&quot;https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-third-party-actions&quot;&gt;Pin actions to a full length commit SHA for security concerns&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;p&gt;We only &lt;a href=&quot;https://docs.docker.com/engine/install/&quot;&gt;install&lt;/a&gt; Docker CE version. For Windows and MacOS, Docker Desktop includes both Docker and &lt;a href=&quot;#docker-compose&quot;&gt;Docker Compose&lt;/a&gt;. On Linux, it is highly recommended to install Docker and Docker Compose by &lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository&quot;&gt;official repo&lt;/a&gt;, or install by &lt;a href=&quot;https://docs.docker.com/engine/install/ubuntu/#install-from-a-package&quot;&gt;downloaded packages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On Amazon Linux 2, we can install Docker by package manager, and then install Docker Compose by &lt;a href=&quot;https://docs.docker.com/compose/install/#install-the-binary-manually&quot;&gt;downloading binary file manually&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Install Docker by package manager:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum update &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# CentOS&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;docker

&lt;span class=&quot;c&quot;&gt;# Amazon Linux 2 - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-container-image.html&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;amazon-linux-extras &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;docker

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order to run &lt;em&gt;docker&lt;/em&gt; as a normal user, add the account to &lt;em&gt;docker&lt;/em&gt; group:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;usermod &lt;span class=&quot;nt&quot;&gt;-aG&lt;/span&gt; docker &amp;lt;username&amp;gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Install Docker Compose manually:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /usr/local/lib/docker/cli-plugins
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-sSL&lt;/span&gt; https://github.com/docker/compose/releases/latest/download/docker-compose-&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;-&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; /usr/local/lib/docker/cli-plugins/docker-compose

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; +x /usr/local/lib/docker/cli-plugins/docker-compose
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker compose version

~ &lt;span class=&quot;nv&quot;&gt;$ PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/lib/docker/cli-plugins:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker-compose version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;start-daemon&quot;&gt;Start daemon&lt;/h1&gt;

&lt;p&gt;Start Docker Engine.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;docker
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl status docker
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl start docker

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker info
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker ps
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker compose &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All data is located in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/lib/docker&lt;/code&gt; directory.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ubuntu@ip-172-31-9-194:~/misc&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /var/lib/docker/
buildkit  containers  engine-id  image  network  overlay2  plugins  runtimes  swarm  tmp  volumes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;dockersock&quot;&gt;docker.sock&lt;/h2&gt;

&lt;p&gt;The daemon listens for RESTful API requests via either an Unix socket file at &lt;a href=&quot;https://docs.docker.com/reference/cli/dockerd/#daemon-socket-option&quot;&gt;/var/run/docker.sock&lt;/a&gt; or an &lt;a href=&quot;#architecture&quot;&gt;IP address&lt;/a&gt;. By default only the Unis socket file is enabled. See &lt;a href=&quot;#docker-context&quot;&gt;Docker Context&lt;/a&gt; for enabling the IP socket.&lt;/p&gt;

&lt;p&gt;We can communicate with the daemon directly with cURL according to the &lt;a href=&quot;https://docs.docker.com/reference/api/engine/&quot;&gt;Docker API spec&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--unix-socket&lt;/span&gt; /var/run/docker.sock &lt;span class=&quot;nt&quot;&gt;--no-buffer&lt;/span&gt; http://localhost/events
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--unix-socket&lt;/span&gt; /var/run/docker.sock http://localhost/version
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--unix-socket&lt;/span&gt; /var/run/docker.sock http://localhost/images/json | jq
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--unix-socket&lt;/span&gt; /var/run/docker.sock http://localhost/containers/json | jq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can also create containers inside another container by &lt;a href=&quot;#data-share&quot;&gt;mounting&lt;/a&gt; the socket file, as long as &lt;a href=&quot;https://askubuntu.com/a/1388299/226303&quot;&gt;docker CLI is available&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# on host use the special &apos;docker&apos; image&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; docker-sock &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; /var/run/docker.sock:/var/run/docker.sock docker sh

&lt;span class=&quot;c&quot;&gt;# within docker-sock&lt;/span&gt;
/ &lt;span class=&quot;c&quot;&gt;# docker run --name docker-in-docker --rm -it ubuntu bash&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# within docker-in-docker&lt;/span&gt;
root@978d8704d548:/#
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the host terminal, we can retrieve the &lt;em&gt;nested&lt;/em&gt; containers&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS           NAMES
978d8704d548   ubuntu    &lt;span class=&quot;s2&quot;&gt;&quot;bash&quot;&lt;/span&gt;                   5 seconds ago    Up 4 seconds                    docker-in-docker
a3b93da63e90   docker    &lt;span class=&quot;s2&quot;&gt;&quot;dockerd-entrypoint.…&quot;&lt;/span&gt;   17 seconds ago   Up 16 seconds   2375-2376/tcp   docker-sock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can also get all containers from within &lt;em&gt;docker-sock&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/ &lt;span class=&quot;c&quot;&gt;# docker ps -a&lt;/span&gt;
CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS                       PORTS                NAMES
a3b93da63e90   docker                   &lt;span class=&quot;s2&quot;&gt;&quot;dockerd-entrypoint.…&quot;&lt;/span&gt;   4 minutes ago   Up 4 minutes                 2375-2376/tcp        docker-sock
0dadcbdeb804   862614378b4c             &lt;span class=&quot;s2&quot;&gt;&quot;docker-entrypoint.s…&quot;&lt;/span&gt;   13 months ago   Exited &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 13 months ago                          eloquent_jones
f3f0faf83ac5   docker/getting-started   &lt;span class=&quot;s2&quot;&gt;&quot;/docker-entrypoint.…&quot;&lt;/span&gt;   14 months ago   Exited &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;255&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 13 months ago   0.0.0.0:80-&amp;gt;80/tcp   romantic_colden
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, mounting &lt;em&gt;docker.sock&lt;/em&gt; would make your host &lt;a href=&quot;https://dev.to/pbnj/docker-security-best-practices-45ih#docker-engine&quot;&gt;vulnerable to attack&lt;/a&gt; as Docker daemon within the container is ran as &lt;em&gt;root&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;docker-context&quot;&gt;Docker Context&lt;/h1&gt;

&lt;p&gt;Recall that Docker works &lt;a href=&quot;#architecture&quot;&gt;in client-server mode&lt;/a&gt;, where the client connects to the server via RESTful API. As a developer, it is not unusual that we have different environment of different purposes such as development environment, staging environment, buildx environment, production environment, etc.&lt;/p&gt;

&lt;p&gt;For a single &lt;em&gt;docker&lt;/em&gt; CLI to communicate with different Docker Engines, we have &lt;a href=&quot;https://docs.docker.com/engine/manage-resources/contexts/&quot;&gt;Docker Context&lt;/a&gt;. A context is a profile recording the information of a Docker Engine like the IP address. To swtich between Docker Engines, just use &lt;em&gt;docker context&lt;/em&gt; CLI.&lt;/p&gt;

&lt;p&gt;By default, only the local Unix socket is enabled. The example below enables IP socket listening and but only binds to localhost for demo purpose. To expose the Docker Engine on public Internet, please follow the guide at &lt;a href=&quot;https://docs.docker.com/engine/security/protect-access/&quot;&gt;security concern&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl editedit docker.service
&lt;span class=&quot;c&quot;&gt;# /etc/systemd/system/docker.service.d/override.conf&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Service]
&lt;span class=&quot;nv&quot;&gt;ExecStart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;ExecStart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/bin/dockerd &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; fd:// &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; tcp://127.0.0.1:2375 &lt;span class=&quot;nt&quot;&gt;--containerd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/run/containerd/containerd.sock

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl daemon-reload

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart docker

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ps &lt;span class=&quot;nt&quot;&gt;-eFH&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;d]ockerd
root       24927       1  0 552268 77412  3 07:29 ?        00:00:00   /usr/bin/dockerd &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; fd:// &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; tcp://127.0.0.1:2375 &lt;span class=&quot;nt&quot;&gt;--containerd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/run/containerd/containerd.sock

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-sS&lt;/span&gt; http://localhost:2375/containers/json | jq &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;.[].Names&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;/httpbin&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;cli-sample&quot;&gt;CLI Sample&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fgrep &lt;span class=&quot;nt&quot;&gt;-qa&lt;/span&gt; docker /proc/1/cgroup&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;                    &lt;span class=&quot;c&quot;&gt;# check if it is within a docker or on the host&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker info                                                 &lt;span class=&quot;c&quot;&gt;# display the outline of docker environment&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker image/container &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;                              &lt;span class=&quot;c&quot;&gt;# list images/containers&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;image] &lt;span class=&quot;nb&quot;&gt;history&lt;/span&gt;                                      &lt;span class=&quot;c&quot;&gt;# show layers of an image&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker inspect &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; name | ID &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;                                &lt;span class=&quot;c&quot;&gt;# display low-level details on any docker objects&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker logs &amp;lt;container&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is the full list of docker CLI: &lt;a href=&quot;https://docs.docker.com/engine/reference/commandline/docker/&quot;&gt;Docker CLI&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;pull-image&quot;&gt;Pull Image&lt;/h1&gt;

&lt;p&gt;It is highly recommended to &lt;em&gt;pull&lt;/em&gt; the &lt;a href=&quot;https://hub.docker.com/r/docker/getting-started&quot;&gt;docker/getting-started&lt;/a&gt; image, &lt;em&gt;run&lt;/em&gt; and visit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker search &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; is-official&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;true &lt;/span&gt;ubuntu                    &lt;span class=&quot;c&quot;&gt;# search only official image&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker pull ubuntu:16.04                                    &lt;span class=&quot;c&quot;&gt;# specify a tag&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker pull ubuntu@sha256:&amp;lt;&lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;                            &lt;span class=&quot;c&quot;&gt;# specify an image ID&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker images
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;docker search&lt;/em&gt; search docker images from registries defined in &lt;em&gt;/etc/container/registries.conf&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Unfortunately, it does &lt;em&gt;not&lt;/em&gt; suport tags or IDs. Instead, go to the registry website or check third party tool &lt;a href=&quot;https://github.com/HariSekhon/DevOps-Python-tools&quot;&gt;DevOps-Python-tools&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;We can offer &lt;em&gt;docker pull&lt;/em&gt; a tag (i.e. &apos;ubuntu:latest&apos;) or an &lt;em&gt;image ID&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When pulling an image without its digest, we can update the image with the same &lt;em&gt;pull&lt;/em&gt; command again.&lt;/p&gt;

    &lt;p&gt;On the contrary, with digest, the image is fixed and pinned to that exact version. This makes sure you are interacting with the exact image. However, upcoming security fixes are also missed.&lt;/p&gt;

    &lt;p&gt;To get image digest, we either go to the official registry, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;images --digests&lt;/code&gt;, or even &lt;em&gt;inspect&lt;/em&gt; command.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Any any time, Ctrl-C terminates the pull process.&lt;/li&gt;
  &lt;li&gt;Docker support &lt;a href=&quot;https://docs.docker.com/network/proxy/&quot;&gt;proxy configuration&lt;/a&gt; when feteching the images.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;launch-containers&quot;&gt;Launch Containers&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;docker run&lt;/em&gt; equals &lt;em&gt;docker create&lt;/em&gt; plus &lt;em&gt;docker start&lt;/em&gt;. Usually, we just &lt;em&gt;docker run&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Syntax.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; centos-5.8 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;,src&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/home/jim/workspace/,dst&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/home/jim/workspace/,ro &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; /home/jim/workspace/ &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--net&lt;/span&gt; host
&lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
7a126f3dba08 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
bash

&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
root@docker ~ &lt;span class=&quot;c&quot;&gt;# cat /etc/os-release&lt;/span&gt;
root@docker ~ &lt;span class=&quot;c&quot;&gt;# exit 13&lt;/span&gt;
root@docker ~ &lt;span class=&quot;c&quot;&gt;# echo $?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;When we run an image, a container is created with an extra layer of writable filesystem.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To be compatible with AMD64/ARM64, we can add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--platform linux/x86_64&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--platform linux/arm64&lt;/code&gt;. Check &lt;a href=&quot;https://github.com/BretFisher/multi-platform-docker-build&quot;&gt;multi-platform-docker-build&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;This also applies to &lt;a href=&quot;#docker-build-dockerfile&quot;&gt;docker build&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;By default, the root process of a container (PID 1), namely the &lt;a href=&quot;#exec-and-shell&quot;&gt;CMD/ENTRYPOINTWITH&lt;/a&gt; is started in the &lt;em&gt;forground&lt;/em&gt; mode. The host terminal is &lt;a href=&quot;#get-into-container&quot;&gt;attached&lt;/a&gt; to the process&apos;s STDOUT/STDERR, but &lt;em&gt;not&lt;/em&gt; STDIN. So we can see the output (error message included) of the root process as follows:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; ubuntu &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /
bin   dev  home  media  opt   root  sbin  sys  usr
boot  etc  lib   mnt    proc  run   srv   tmp  var
   
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; ubuntu &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /
bin
boot
dev
etc
home
lib
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;We can use multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-a&lt;/code&gt; options to control the attachment combinations of STDIN/STDOUT/STDERR. To following example, we can even input to the root process as long as its STDIN is open. Refer to &lt;a href=&quot;https://stackoverflow.com/q/30137135&quot;&gt;confused-about-docker-t-option-to-allocate-a-pseudo-tty&lt;/a&gt; and &lt;a href=&quot;https://docs.docker.com/engine/reference/commandline/run/#attach-to-stdinstdoutstderr--a&quot;&gt;Attach to STDIN/STDOUT/STDERR&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; stdin &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; stdout ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If we want to start the process in &lt;em&gt;background&lt;/em&gt; mode, namely the &lt;em&gt;detach&lt;/em&gt; mode, then add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d&lt;/code&gt; option. Containers runs in this mode will print the container ID and release host terminal immediately. So we cannot input to the root process or see the output or error message: STDIN/STDOUT/STDERR detached. If the root process exits, then the container exits as well. So we cannot do like this:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 80:80 my_image service nginx start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;As the root process &lt;em&gt;service&lt;/em&gt; exits immediately after &lt;em&gt;nginx&lt;/em&gt; is started. The next example will keep the container running as the &lt;em&gt;tail&lt;/em&gt; command persists:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ $ docker run -d ubuntu bash -c &quot;tail -f /dev/null&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; allocates a pseudo-TTY connected for the root process, especially useful when the process is an &lt;em&gt;interactive&lt;/em&gt; Shell. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i&lt;/code&gt; option forces the process&apos;s STDIN to be open and runs the container interactively, so we can &lt;em&gt;input&lt;/em&gt; some data to the process directly, which works even when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d&lt;/code&gt; is present. Here is an example:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo test&lt;/span&gt; | docker run &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; ubuntu &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; -
&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The two options are usually used together for Shell: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; creates a pseudo-TTY, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i&lt;/code&gt; makes the STDIN of the pseudo-TTY open for data input.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# STDIN not open by default, so keeps waiting for input&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dockder run &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; ubuntu bash
   
&lt;span class=&quot;c&quot;&gt;# can input/output, but no standalone STDOUT, reuse that of host terminal&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rum&lt;/span&gt; ubunty bash
   
&lt;span class=&quot;c&quot;&gt;# standalone stdin/stdout/stderr, also interactive for input&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rum&lt;/span&gt; ubunty bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--rm&lt;/code&gt; automatically remove the container when it exits.&lt;/li&gt;
  &lt;li&gt;Check &lt;a href=&quot;#data-share&quot;&gt;Data Share&lt;/a&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mount&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-w&lt;/code&gt; lets the root process running inside the given directory that is created on demand.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--net, --network&lt;/code&gt; connects the container to a network. By default, it is &lt;em&gt;bridge&lt;/em&gt;. Details are discussed in later sections.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-u, --user&lt;/code&gt; runs the root process as a non-root user. Attention that, the username is that within the container. So the image creator should create that name in Dockerfile.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;bash&lt;/em&gt; overrides the CMD/ENTRYPOINT instructions of the image.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is a note about the different options:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/docker-run-adit.jpg&quot; alt=&quot;docker run&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Please also follow this post &lt;a href=&quot;https://stackoverflow.com/q/71761103/2336707&quot;&gt;Cannot pipe to docker run with stdin attached&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;runtime-metrics&quot;&gt;Runtime metrics&lt;/h1&gt;

&lt;p&gt;Please see &lt;a href=&quot;https://docs.docker.com/engine/containers/runmetrics/&quot;&gt;https://docs.docker.com/engine/containers/runmetrics/&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;data-share&quot;&gt;Data Share&lt;/h1&gt;

&lt;p&gt;Docker containers can read from or write to pathnames, either on host or on memory filesystem - to share data. There are &lt;a href=&quot;https://docs.docker.com/storage/&quot;&gt;three storage types&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Volume, Data Volume, or Named Volume.&lt;/p&gt;

    &lt;p&gt;By default, running data of a container is layered on top of the image used to create it. A &lt;em&gt;volume&lt;/em&gt; decouples that data from both the host or the container. Just think of a Windows partition or removable disk drive.&lt;/p&gt;

    &lt;p&gt;Volumes are managed by Docker and persist. Data within can be shared among multiple containers, as well as between the host and a container.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Beofre you restart a docker compose project, please run &quot;docker volume prune -a&quot;, otherwise history data might interrupt new containers.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Bind Mount.&lt;/p&gt;

    &lt;p&gt;Bind-mount a file or directory in the host to a file or directory in the container. The target can be read-only or read-write. For example, bind host &lt;em&gt;/etc/resolv.conf&lt;/em&gt; to a container, sharing name servers.&lt;/p&gt;

    &lt;p&gt;Attention please; to bind-mount a file, please provide the absolute path, otherwise the dest pathname in the container might be a directory! Check &lt;a href=&quot;https://stackoverflow.com/q/42248198/2336707&quot;&gt;How to mount a single file in a volume&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmpfs&lt;/code&gt; Mount.&lt;/p&gt;

    &lt;p&gt;Needless to say, &lt;em&gt;tmpfs&lt;/em&gt; is a memory filesystem that let container stores data in host memory.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We use option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--volume , -v&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mount&lt;/code&gt; to share data between containers and hosts. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mount&lt;/code&gt; is recommended as it support all 3 kinds of data sharing and is more verbose. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--volume&lt;/code&gt; will be deprecated soon.&lt;/p&gt;

&lt;p&gt;If the file or directory on the host does not exist. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--volume&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mount&lt;/code&gt; behaves differently. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--volume&lt;/code&gt; would create the pathname as a &lt;em&gt;directory&lt;/em&gt;, NOT a file, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mount&lt;/code&gt; would report error.&lt;/p&gt;

&lt;p&gt;On the other hand, if the target pathname already exists in the container, both options would &lt;em&gt;obsecure&lt;/em&gt; contents over there. This is useful if we&apos;d like to test a new version of code without touching the original copies.&lt;/p&gt;

&lt;h2 id=&quot;env-variables&quot;&gt;ENV Variables&lt;/h2&gt;

&lt;p&gt;To pass environment variables to containers, we can:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e, --env&lt;/code&gt; applies &lt;a href=&quot;https://stackoverflow.com/q/49293967/2336707&quot;&gt;only&lt;/a&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run&lt;/code&gt;. This method &lt;a href=&quot;https://stackoverflow.com/a/30494145/2336707&quot;&gt;reveal&lt;/a&gt; sensitive values in Shell history. We can firstly &lt;em&gt;export&lt;/em&gt; the variable on CLI, then pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--env VAR&lt;/code&gt; without the value part.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/compose/env-file/&quot;&gt;–env-file&lt;/a&gt; (default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PWD/.env&lt;/code&gt;) applies both to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run&lt;/code&gt; and &lt;a href=&quot;#docker-compose&quot;&gt;docker compose&lt;/a&gt;. This fits when there are a lot of variables to pass in.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#docker-compose&quot;&gt;docker compose&lt;/a&gt; can pick up &lt;a href=&quot;https://docs.docker.com/compose/reference/envvars/&quot;&gt;a few compose-specific variables&lt;/a&gt; from CLI, so just &lt;em&gt;export&lt;/em&gt; it.&lt;/li&gt;
  &lt;li&gt;CLI variables can also be for &lt;a href=&quot;https://docs.docker.com/compose/compose-file/compose-file-v3/#variable-substitution&quot;&gt;substitution in compose file&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;selinux&quot;&gt;SELinux&lt;/h2&gt;

&lt;p&gt;When bind-mount a file or mount a directory of host, SELinx policy in the container &lt;a href=&quot;https://stackoverflow.com/q/24288616&quot;&gt;may restrict access&lt;/a&gt; to the shared pathname.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Temporarily turn off SELinux policy:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;su &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;setenforce 0&quot;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker restart container-ID
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Adding a SELinux rule for the shared pathname:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chcon&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Rt&lt;/span&gt; svirt_sandbox_file_t /path/to/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Pass argument &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:z&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Z&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--volume&lt;/code&gt; option:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; /root/workspace:/root/workspace:z
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Attention please, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mount&lt;/code&gt; does not support this.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--privileged=true&lt;/code&gt; to &lt;em&gt;docker run&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;However, this method is discouraged as privileged containers bring in security risks. If it is the last resort, first create a privileged container and then create a non-priviledged container inside.&lt;/p&gt;

    &lt;p&gt;Privilege permissions can have fine-grained control by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cap-add&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cap-drop&lt;/code&gt;, which is recommended!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;nginx-container-sample&quot;&gt;Nginx Container Sample&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; webserver &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--net&lt;/span&gt; host
&lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;,source&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/tmp/logs,target&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/log/nginx &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8080:80 nginx

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker container &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker container logs webserver
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker container stop/kill webserver
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker container start webserver
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker container &lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;webserve          &lt;span class=&quot;c&quot;&gt;# remove one or more container (even running instances)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker container prune                &lt;span class=&quot;c&quot;&gt;# remove all stopped container&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt; maps host port 8080 to container port 80 that is already bound to host Nginx process.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Check the Dockerfile, there is a line telling how Nginx should be started:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CMD [&quot;nginx&quot;, &quot;-g&quot;, &quot;daemon off;&quot;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--mount&lt;/code&gt; type is a &lt;a href=&quot;#data-share&quot;&gt;Bind Mount&lt;/a&gt; directory.&lt;/li&gt;
  &lt;li&gt;Visit the Nginx container page at &lt;em&gt;http://host-ip:8080&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;stop&lt;/em&gt; attempts to trigger a &lt;a href=&quot;https://superuser.com/a/757497&quot;&gt;&lt;em&gt;graceful&lt;/em&gt;&lt;/a&gt; shutdown by sending the standard POSIX signal SIGTERM, whereas &lt;em&gt;kill&lt;/em&gt; just kills the process by sending SIGKILL signal.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;get-into-container&quot;&gt;Get into Container&lt;/h2&gt;

&lt;p&gt;Exec a simple command in container:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;webserver sh &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;echo $PATH&apos;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;webserver ps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sometimes, we want to exec the command in the background when we do not care about its output or need not any input:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; webserver &lt;span class=&quot;nb&quot;&gt;touch&lt;/span&gt; /tmp/test.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we want to interactively and continuously control the container:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; webserver bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Apart from &lt;em&gt;docker exec&lt;/em&gt;, &lt;a href=&quot;https://docs.docker.com/engine/reference/commandline/attach/&quot;&gt;docker attach &amp;lt;container&amp;gt;&lt;/a&gt; is also recommended.&lt;/p&gt;

&lt;p&gt;This command attaches the host terminal&apos;s STDIN, STDOUT and STDERR files to a running container, allowing interactive control or inspect as if the container was running directly in the host&apos;s terminal. It will display the output of the ENTRYPOINT/CMD process.&lt;/p&gt;

&lt;p&gt;For example, a container can be shutdown by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-c&lt;/code&gt; shortcut, sending the SIGINT signal (identical to SIGTERM) to the container by default. Rather, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-p C-q&lt;/code&gt; detaches from the container and leave it running in the background again.&lt;/p&gt;

&lt;p&gt;If the process is running as PID 1 (like &lt;em&gt;/usr/bin/init&lt;/em&gt;), it ignores any signal and will not terminate on SIGINT or SIGTERM unless it is coded to do so.&lt;/p&gt;

&lt;h1 id=&quot;networking-drivers&quot;&gt;Networking Drivers&lt;/h1&gt;

&lt;p&gt;The Docker&apos;s networking subsystem is &lt;em&gt;pluggable&lt;/em&gt;, using drivers. Docker provides multiple built-in networks, based on which we can &lt;a href=&quot;#self-define-network&quot;&gt;define custom networks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below is a simple explanation:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Bridge&lt;/p&gt;

    &lt;p&gt;The &lt;em&gt;default&lt;/em&gt; driver if none is given upon &lt;em&gt;run&lt;/em&gt;, providing network isolation from the outside. It is to bridge traffic among multiple containers and the host. Check the image below, &lt;em&gt;docker0&lt;/em&gt; is the bridge interface.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/docker-net.png&quot; alt=&quot;docker netowrk&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;If we define a &lt;a href=&quot;#self-define-network&quot;&gt;custom&lt;/a&gt; &lt;em&gt;bridge&lt;/em&gt; network, containers within can communicate with each other by alias or name, otherwise they can &lt;a href=&quot;https://docs.docker.com/network/bridge/#differences-between-user-defined-bridges-and-the-default-bridge&quot;&gt;only&lt;/a&gt; communicate by IP addresses.&lt;/p&gt;

    &lt;p&gt;Pay attention please; this is different from the &lt;em&gt;bridge&lt;/em&gt; mode of VMWare or VirtualBox (real Virtual Machine). VMWare and VirtualBox&apos;s bridge is deployed directly on the host&apos;s interface and appears to be a real physical device parallel to the host and can be connected to from within LAN directly.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://docs.docker.com/network/host/&quot;&gt;Host&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Share the host&apos;s networking directly without isolation. However, LAN devices cannot differntiate between containers and the host as there is not individual IP addressed assigned to containers. The host mode is preferred when the service exposes a port publicly like Nginx servers.&lt;/p&gt;

    &lt;p&gt;To use host network, just add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;network_mode: host&lt;/code&gt; to &lt;a href=&quot;#docker-compose&quot;&gt;Dockder compose file&lt;/a&gt;, and but must remove the &lt;a href=&quot;https://docs.docker.com/compose/compose-file/05-services/#ports&quot;&gt;ports mappings&lt;/a&gt; as containers share the same network as the host. Alternatively, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--network=host&lt;/code&gt; option to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;Unfortunately, &lt;a href=&quot;https://github.com/docker/for-mac/issues/1031&quot;&gt;host mode does not work on macOS&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Overlay&lt;/p&gt;

    &lt;p&gt;Overlay connects multiple Docker daemons together, creating a distributed network among multiple Docker daemon hosts. This network sits on top of (overlays) the host-specific networks, allowing containers connected to it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;macvlan&lt;/p&gt;

    &lt;p&gt;As the name implied, maclan assignes a MAC address to a container, making it be a physical device on the same network as the host - counterpart of VMWare/VirtualBox&apos;s &apos;bridge&apos;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;none&lt;/p&gt;

    &lt;p&gt;Disable networking.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;dns&quot;&gt;DNS&lt;/h2&gt;

&lt;p&gt;Docker Destkop has multiple built-in DNS servers as follows.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/docker-desktop-dns.png&quot; alt=&quot;docker-desktop-dns.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When resolving containers within the the same Docker network, the internal DNS within &lt;em&gt;dockerd&lt;/em&gt; is utilized. However, resolving hostnames outside of the Docker network, would be forwarded to host via CoreDNS.&lt;/p&gt;

&lt;p&gt;Please read &lt;a href=&quot;https://www.docker.com/blog/how-docker-desktop-networking-works-under-the-hood/&quot;&gt;How Docker Desktop Networking Works Under the Hood&lt;/a&gt; regarding how Docker Destop achieves DNS, HTTP Proxy, TCP/IP stack, Port Forwarding, etc. network features via &lt;em&gt;vpnkit&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;hostdockerinternal&quot;&gt;host.docker.internal&lt;/h2&gt;

&lt;p&gt;Occasionally, we want to access to host services from within containers.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If the container is booted with &lt;a href=&quot;#networking-drivers&quot;&gt;host network&lt;/a&gt;, then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;127.0.0.1&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;If the container is booted with &lt;a href=&quot;#networking-drivers&quot;&gt;bridge network&lt;/a&gt;, then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host.docker.internal&lt;/code&gt;. Depending on the platform, we might &lt;a href=&quot;https://stackoverflow.com/a/62431165/2336707&quot;&gt;need a bit setup&lt;/a&gt;.
    &lt;ol&gt;
      &lt;li&gt;On macOS, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host.docker.internal&lt;/code&gt; is intuitively supported.&lt;/li&gt;
      &lt;li&gt;On Linux, we should manually add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;host.docker.internal:host-gateway&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run --add-host&lt;/code&gt; or to &lt;a href=&quot;https://docs.docker.com/compose/compose-file/05-services/#extra_hosts&quot;&gt;extra_hosts&lt;/a&gt; of &lt;a href=&quot;#docker-compose&quot;&gt;docker compose&lt;/a&gt;. This would add an entry in &quot;/etc/hosts&quot;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The hostname &quot;host.docker.internal&quot; is used only for connection, so please set the correct &quot;Host&quot; header. See example below.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; alpine sh

/ &lt;span class=&quot;c&quot;&gt;# curl -v http://localhost/anything --connect-to localhost:80:host.docker.internal:80&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; processing: http://localhost/anything
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; Connecting to &lt;span class=&quot;nb&quot;&gt;hostname&lt;/span&gt;: host.docker.internal
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; Connecting to port: 80
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;   Trying 192.168.65.254:80...
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; Connected to host.docker.internal &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;192.168.65.254&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; port 80
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; GET /anything HTTP/1.1
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; Host: localhost
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; User-Agent: curl/8.2.1
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; Accept: &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&amp;lt; HTTP/1.1 200 OK
&amp;lt; Server: openresty/1.21.4.2rc1
&amp;lt; Date: Sat, 05 Aug 2023 06:45:34 GMT
&amp;lt; Content-Type: application/json
&amp;lt; Transfer-Encoding: chunked
&amp;lt; Connection: close
&amp;lt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;message&quot;&lt;/span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;hello, world&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; Closing connection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;self-define-network&quot;&gt;Self-define Network&lt;/h2&gt;

&lt;p&gt;Docker automates network configuration upon container startup. We can customize that on purpose.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker network &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker network create &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; bridge mynet
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; ubt1604 &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; /src/hostdir:/opt/condir:rw &lt;span class=&quot;nt&quot;&gt;--network&lt;/span&gt; mynet ubuntu:16.04
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker network inspect mynet
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--net&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--network&lt;/code&gt; option. To the &apos;host&apos; networking driver, just pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--net host&lt;/code&gt; option to &lt;em&gt;docker run&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;ssh-agent-forwarding&quot;&gt;SSH Agent Forwarding&lt;/h2&gt;

&lt;p&gt;In order not to set up a new SSH environment within containers, we can &lt;a href=&quot;https://docs.docker.com/desktop/networking/#ssh-agent-forwarding&quot;&gt;forward SSH agent on host to container&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;a href=&quot;https://docs.docker.com/desktop/&quot;&gt;Docker Desktop&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; root &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;type=bind,src=/run/host-services/ssh-auth.sock,target=/run/host-services/ssh-auth.sock,ro&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;SSH_AUTH_SOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/run/host-services/ssh-auth.sock&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--entrypoint&lt;/span&gt; /bin/bash kong/kong-gateway:latest

root@3442a4bc63cd:/# ssh-add &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For &lt;a href=&quot;https://docs.docker.com/engine/&quot;&gt;Docker engine&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; root &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;type=bind,src=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SSH_AUTH_SOCK&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,target=/run/host-services/ssh-auth.sock,ro&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;SSH_AUTH_SOCK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/run/host-services/ssh-auth.sock&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--entrypoint&lt;/span&gt; /bin/bash kong/kong-gateway:latest

root@3442a4bc63cd:/# ssh-add &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It may report permission issue. We should add the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w&lt;/code&gt; (write) permission to the socket file. Do it on the host and/or within the container. The example below shows the socket file disallows &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;w&lt;/code&gt; by &quot;others&quot; that the &quot;kong&quot; account belongs to. See &lt;a href=&quot;https://github.com/docker/for-mac/issues/7204&quot;&gt;macOS SSH agent forwarding not working any longer&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# in the container&lt;/span&gt;
kong@66cbbf96f403:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh-add &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
Error connecting to agent: Permission denied

kong@66cbbf96f403:/&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SSH_AUTH_SOCK&lt;/span&gt;
srwxrwxr-x 1 501 ubuntu 0 Jan  2 13:11 /run/host-services/ssh-auth.sock

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod &lt;/span&gt;o+w /run/host-services/ssh-auth.sock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attention that, if you are SSH into Linux VPS from macOS, the SSH agent might be forwarded to the Linux VPS, depending on the SSH config on macOS. This is totally a different topic. Containers in the Linux VPS has no access to the forwarded macOS SSH agent, and we should launch a new one in the Linux VPS.&lt;/p&gt;

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

&lt;p&gt;The legacy communication method is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--link&lt;/code&gt;. Docker copies information (e.g. &lt;a href=&quot;#env-variables&quot;&gt;ENV Variables&lt;/a&gt;) from &lt;em&gt;source&lt;/em&gt; container to &lt;em&gt;receipt&lt;/em&gt; (&lt;em&gt;target&lt;/em&gt;) container, and provides network access from receipt container to source container.&lt;/p&gt;

&lt;p&gt;Take &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker run --name web --link postgres:alias ...&lt;/code&gt; for example, the newly created &lt;em&gt;web&lt;/em&gt; is receipt container and the existing &lt;em&gt;postgres&lt;/em&gt; is source container.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--link&lt;/code&gt; is amost &lt;a href=&quot;https://docs.docker.com/network/links/&quot;&gt;deprecated&lt;/a&gt; as we can use other features to accomplish the same functionalities. For example, for info copy, use &lt;a href=&quot;#env-variables&quot;&gt;ENV Variables&lt;/a&gt; or &lt;a href=&quot;#data-share&quot;&gt;data share&lt;/a&gt;. For network communication, just follow &lt;a href=&quot;#network-drivers&quot;&gt;Networking Drivers&lt;/a&gt; and &lt;a href=&quot;#self-define-network&quot;&gt;Self-define Network&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;## source container&lt;/span&gt;

13:47:23 zachary@Zacharys-MacBook-Pro ~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; postgres &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;HELLO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;world &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;POSTGRES_HOST_AUTH_METHOD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;trust &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; postgres:14
25732d58f238b1d3e83fc52ea3c8b91f75290385066e6541d616e68eecd6cfdd

13:47:39 zachary@Zacharys-MacBook-Pro ~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; postgres bash
root@25732d58f238:/# &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HELLO&lt;/span&gt;
world


&lt;span class=&quot;c&quot;&gt;## receipt/target container&lt;/span&gt;

13:48:11 zachary@Zacharys-MacBook-Pro ~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; ubuntu &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--link&lt;/span&gt; postgres:db ubuntu bash

&lt;span class=&quot;c&quot;&gt;# src in hosts&lt;/span&gt;
root@8e95191dba0e:/# &lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3      db 25732d58f238 postgres
172.17.0.4      8e95191dba0e

&lt;span class=&quot;c&quot;&gt;# src ENVs&lt;/span&gt;
root@8e95191dba0e:/# &lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;DB_ | &lt;span class=&quot;nb&quot;&gt;sort
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DB_ENV_GOSU_VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1.14
&lt;span class=&quot;nv&quot;&gt;DB_ENV_HELLO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;world
&lt;span class=&quot;nv&quot;&gt;DB_ENV_LANG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;en_US.utf8
&lt;span class=&quot;nv&quot;&gt;DB_ENV_PGDATA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/var/lib/postgresql/data
&lt;span class=&quot;nv&quot;&gt;DB_ENV_PG_MAJOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;14
&lt;span class=&quot;nv&quot;&gt;DB_ENV_PG_VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;14.4-1.pgdg110+1
&lt;span class=&quot;nv&quot;&gt;DB_ENV_POSTGRES_HOST_AUTH_METHOD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;trust
&lt;span class=&quot;nv&quot;&gt;DB_NAME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/ubuntu/db
&lt;span class=&quot;nv&quot;&gt;DB_PORT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;tcp://172.17.0.3:5432
&lt;span class=&quot;nv&quot;&gt;DB_PORT_5432_TCP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;tcp://172.17.0.3:5432
&lt;span class=&quot;nv&quot;&gt;DB_PORT_5432_TCP_ADDR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;172.17.0.3
&lt;span class=&quot;nv&quot;&gt;DB_PORT_5432_TCP_PORT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5432
&lt;span class=&quot;nv&quot;&gt;DB_PORT_5432_TCP_PROTO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;tcp

&lt;span class=&quot;c&quot;&gt;# src network&lt;/span&gt;
root@8e95191dba0e:/# ping db
PING db &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;172.17.0.3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 56&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;84&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; bytes of data.
64 bytes from db &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;172.17.0.3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: &lt;span class=&quot;nv&quot;&gt;icmp_seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 &lt;span class=&quot;nv&quot;&gt;ttl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;64 &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.210 ms
64 bytes from db &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;172.17.0.3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: &lt;span class=&quot;nv&quot;&gt;icmp_seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2 &lt;span class=&quot;nv&quot;&gt;ttl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;64 &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.452 ms
64 bytes from db &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;172.17.0.3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: &lt;span class=&quot;nv&quot;&gt;icmp_seq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3 &lt;span class=&quot;nv&quot;&gt;ttl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;64 &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.136 ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attention please; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--link&lt;/code&gt; is one-way link only. Info is transferred from source containers to receipt containers but source containers know nothing about receipt containers. To achieve bi-directional communication, please use &lt;a href=&quot;#networking-drivers&quot;&gt;network&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;exec-and-shell&quot;&gt;exec and shell&lt;/h1&gt;

&lt;p&gt;Usually, in the end of image, we have three kinds of &lt;em&gt;instruction&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;RUN. Creates a new layer of image. Usually used to install package. It&apos;s recommended to install multiple packages in a single RUN instruction so that we have less image layers.&lt;/li&gt;
  &lt;li&gt;CMD. Set the default command to run when &lt;em&gt;run&lt;/em&gt; a container.&lt;/li&gt;
  &lt;li&gt;ENTRYPOINT. &lt;em&gt;run&lt;/em&gt; a container as a command, so that we can provide extra arguments when &lt;em&gt;run&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Refer to &lt;a href=&quot;http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/&quot;&gt;RUN, ENTRYPOINT and CMD&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;Each instruction has two kinds of running forms:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;shell form.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;instruction&amp;gt; cmd arg1 arg2 ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;By default, &lt;em&gt;/bin/sh&lt;/em&gt; will be used to run the &lt;em&gt;cmd&lt;/em&gt; as:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/bin/sh -c &apos;cmd arg1 arg2 ...&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;It is the preferred form of the RUN instruction to install package in the image and exit.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;exec form.&lt;/p&gt;

    &lt;p&gt;The &lt;em&gt;cmd&lt;/em&gt; is ran directly without any Shell involvement, which is the preferred form of CMD and ENTRYPOINT as we usually launch a daemon background within the container. No need to maintain a Shell process.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;instruction&amp;gt; [&quot;cmd&quot;, &quot;arg1&quot;, &quot;arg2&quot;, ...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If we want to run the &lt;em&gt;cmd&lt;/em&gt; with Bash, we can use the exec form but explicitly invoke &lt;em&gt;/bin/bash&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;instruction&amp;gt; [&quot;/bin/bash&quot;, &quot;-c&quot;, &quot;cmd&quot;, &quot;arg1&quot;, &quot;arg2&quot;, ...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://www.cnblogs.com/sparkdev/p/8461576.html&quot;&gt;exec form or sh form&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;When there are multiple CMD or ENTRYPOINT instructions inherited from different image layers, only that of the topmost layer is respected! We can use &lt;em&gt;docker container inspect&lt;/em&gt; to show the instructions and their forms. For example, &lt;em&gt;nginx&lt;/em&gt; image has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMD [&quot;nginx&quot;, &quot;-g&quot;, &quot;daemon off;&quot;]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can pass custom commands and arguments when invoking &lt;em&gt;docker run&lt;/em&gt;, which will override the CMD instruction and arguments thereof. If there exists the ENTRYPOINT instruction in exec form, then custom arguments would be appended to the ENTRYPOINT &lt;em&gt;cmd&lt;/em&gt;. By default, ENTRYPOINT exec form will take extra arguments from CMD instruction in shell form. Custom arguments when &lt;em&gt;docker run&lt;/em&gt; will override those in the CMD instruction. ENTRYPOINT in shell form would ignore custom arguments from CMD or &lt;em&gt;docker run&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We can override ENTRYPOINT and/or CMD as follows.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# docker run --entrypoint /path/to/cmd &amp;lt;image&amp;gt; -a arg1 -b arg2 arg3&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--entrypoint&lt;/span&gt; /bin/bash &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; nginx

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--entrypoint&lt;/span&gt; /bin/bash kong/kong-gateway:latest &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;kong version&quot;&lt;/span&gt;
Kong Enterprise 3.6.1.0

&lt;span class=&quot;c&quot;&gt;# docker run --entrypoint &apos;&apos; &amp;lt;image&amp;gt; /path/to/cmd -a arg1 -b arg2 arg3&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--entrypoint&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; kong/kong-gateway:latest /bin/bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;kong version&quot;&lt;/span&gt;
Kong Enterprise 3.6.1.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is an illustration between CMD and ENTRYPOINT:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/cmd-entrypoint.png&quot; alt=&quot;cmd-entrypoint&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://docs.docker.com/engine/reference/builder/&quot;&gt;Dockerfile reference&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h1 id=&quot;custom-image&quot;&gt;Custom Image&lt;/h1&gt;

&lt;h2 id=&quot;docker-commit&quot;&gt;Docker Commit&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; webserver bash
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
root@docker ~ &lt;span class=&quot;c&quot;&gt;# echo &apos;&amp;lt;h1&amp;gt;Hello, Docker!&amp;lt;/h1&amp;gt;&apos; &amp;gt; /usr/share/nginx/html/index.html&lt;/span&gt;
root@docker ~ &lt;span class=&quot;c&quot;&gt;# exit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker diff webserver
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker container commit &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;jim&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;change front page&apos;&lt;/span&gt; webserver nginx:v2
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker image &lt;span class=&quot;nb&quot;&gt;ls &lt;/span&gt;nginx
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;history &lt;/span&gt;nginx:v2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;We modified container layer storage. Use &lt;em&gt;diff&lt;/em&gt; to check details.&lt;/li&gt;
  &lt;li&gt;Visit the Nginx container page again.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;commit&lt;/em&gt; records modification as a new layer and create a new image.&lt;/p&gt;

    &lt;p&gt;Avoid &lt;em&gt;commit&lt;/em&gt; command as miscellaneous operations (garbage) are recorded either. As discussed in &quot;Data Share&quot; section, we can make use of Volume, Bind Mount, or tmpfs, or resort to &apos;Build Image by Dockerfile&apos; section below.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To verify the new image:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; web2 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8081:80 &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; nginx:v2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--rm&lt;/code&gt; tells to remove the container upon exit.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We can &lt;em&gt;inspect&lt;/em&gt; the target image, and will find &quot;ContainerConfig&quot; and &quot;Config&quot;. They are almost identical.&lt;/p&gt;

    &lt;p&gt;&quot;ContainerConfig&quot; is the config of current container from within this image is committed, while the &quot;Config&quot; is the exact configuration of the image. Pay attention to the &lt;a href=&quot;#exec-and-shell&quot;&gt;Cmd&lt;/a&gt; parts. If we &lt;a href=&quot;#docker-build-dockerfile&quot;&gt;build by Dockerfile&lt;/a&gt;, then they looks different. The ContainerConfig this is the temporary container spawned to create the image. Check &lt;a href=&quot;https://stackoverflow.com/q/36216220&quot;&gt;what-is-different-of-config-and-containerconfig-of-docker-inspect&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;docker-build-dockerfile&quot;&gt;Docker Build Dockerfile&lt;/h2&gt;

&lt;p&gt;From &lt;a href=&quot;#docker-commit&quot;&gt;commit&lt;/a&gt; example above, we can create new image layer but many negligible commands like &lt;em&gt;ls&lt;/em&gt;, &lt;em&gt;pwd&lt;/em&gt;, etc. are recourded as well.&lt;/p&gt;

&lt;p&gt;Similar to Makefile, Docker uses Dockerfile to define image with specified &lt;em&gt;instruction&lt;/em&gt;s like FROM, COPY, RUN etc. Each instruction creates a new intermediate layer and a new intermediate image. In order to minimize number of layers and images, we&apos;d better merge instructions as much as possible.&lt;/p&gt;

&lt;p&gt;In this section, we use Dockerfile to create image &lt;em&gt;nginx:v2&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;mynginx
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;mynginx
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vim Dockerfile
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
FROM nginx
RUN &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;h1&amp;gt;Hello, Docker!&amp;lt;/h1&amp;gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /usr/share/nginx/html/index.html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Just two lines! FROM imports the &lt;a href=&quot;https://docs.docker.com/build/building/base-images/&quot;&gt;base image&lt;/a&gt; on which we will create the new layer. If we do not want any base image, use the &lt;a href=&quot;https://docs.docker.com/build/building/base-images/#create-a-minimal-base-image-using-scratch&quot;&gt;special null image scratch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now we build the image. Please refer to &lt;a href=&quot;https://docs.docker.com/build/concepts/overview/&quot;&gt;Docker Build Overview&lt;/a&gt; to check the difference between &lt;em&gt;docker buildx&lt;/em&gt; and &lt;em&gt;docker build&lt;/em&gt;. To put it simple, &lt;em&gt;docker build&lt;/em&gt; is wrapper of &lt;em&gt;docker buildx&lt;/em&gt; with default arguments.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ BUILDKIT_PROGRESS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;plain docker buildx build &lt;span class=&quot;nt&quot;&gt;--no-cache&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--load&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; nginx:v3 &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; nginx &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; Dockerfile &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM nginx
 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; b175e7467d66
Step 2/2 : RUN &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;h1&amp;gt;Hello, Docker!&amp;lt;/h1&amp;gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /usr/share/nginx/html/index.html
 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; Running &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;d5baea5c6341
Removing intermediate container d5baea5c6341
 &lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 18cc3a3480f0
Successfully built 18cc3a3480f0
Successfully tagged nginx:v3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; option of &lt;em&gt;docker build&lt;/em&gt; actually refers to name of the target image. We can leave the tag part to use the default &lt;em&gt;latest&lt;/em&gt;. We can also &lt;a href=&quot;https://stackoverflow.com/a/36398336&quot;&gt;supply multiple tags&lt;/a&gt;. From example above, the second tag is the default &lt;em&gt;latest&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;If we specify a name that exists already, we detach that name from an existing image and associate it with the new image. The old image still exist and can be checked the &quot;RepoTags&quot; field of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker inspect &amp;lt;image-id&amp;gt;&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;During the building process, both an intermediate container (d5baea5c6341) and image (18cc3a3480f0) is created for &apos;RUN&apos; instruction.&lt;/p&gt;

    &lt;p&gt;The intermediate container defines a new layer which is then committed to create a new image. Afterwards, the intermediate container is removed, but the intermediate image is kept.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The trailing dot means the current directory is the building &lt;em&gt;context&lt;/em&gt; directory. It is also the default location of the Dockerfile. Sometimes, we exclude some context files from the durectory by the &lt;em&gt;.dockerignore&lt;/em&gt; file, as below:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;.git&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; .dockerignore
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Docker sends all files within context directory to remote Docker engine (daemon). Image can be built without a context directory if we don&apos;t have any supplementary files.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker build &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; nginx:v3 - &amp;lt; /path/to/Dockerfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The hypen character cannot be omitted!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;If there exist multiple CMD/ENTRYPOINT instructions from different layers, only that of the topmost layer will be executed upon container start. All the rest CMD/ENTRYPOINT are overriden.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;After the building, we can run &lt;em&gt;nginx:v3&lt;/em&gt; image:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; web3 &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8081:80 &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; nginx:v3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Apart from builing a new docker image for the web server, we can utilize &apos;Data Share&apos; to attach a Volume or Bind Mount to the base docker image. Build the web server within the attached storage instead.&lt;/li&gt;
  &lt;li&gt;Sometimes, we may want to remove the cache of &lt;em&gt;build&lt;/em&gt;, which can be accomplished by &lt;em&gt;docker builder prune -a&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Here is another Dockerfile instance:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;FROM centos:latest
RUN [/bin/bash, -c, &apos;groupadd -g 1000 username ; useradd -ms /bin/bash -u 1000 -g 1000 username; echo &quot;username:1C2B3A&quot; | chpasswd&apos;]
CMD [&quot;/bin/bash&quot;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Recall that in section &apos;Run an Image&apos;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-u username:groupname&lt;/code&gt; requires that the username and groupname exist when creating the image. Change the account password immedately after the container is created as the initial password is explicitly written in the Dockerfile.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;By default, the &apos;RUN&apos; instruction uses &lt;em&gt;/bin/sh&lt;/em&gt; form. It is replaced by &lt;em&gt;/bin/bash&lt;/em&gt; in this example.&lt;/p&gt;

        &lt;p&gt;Also, multiple relevant shell commands are merged into one single &apos;RUN&apos; instruction. We can also the split the command by line continuation like:&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RUN /bin/bash -c &apos;useradd -ms /bin/bash -u 1000 -g 1000 username ; \
echo &quot;username:1C2B3A&quot; | chpasswd&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Some commands may have ask interactive questions. Please check &lt;a href=&quot;https://serverfault.com/q/949991&quot;&gt;DEBIAN_FRONTEND=noninteractive&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;See &lt;a href=&quot;https://www.zhstar.win/2024/12/27/colima/#multi-platform-build&quot;&gt;multi-platform build&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://docs.docker.com/develop/develop-images/dockerfile_best-practices/&quot;&gt;Best practice for writing Dockerfile&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;share-images&quot;&gt;Share Images&lt;/h1&gt;

&lt;p&gt;We can &lt;a href=&quot;https://docs.docker.com/get-started/04_sharing_app/&quot;&gt;share&lt;/a&gt; our own docker image to a registry (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker.io&lt;/code&gt;) by &lt;em&gt;docker push&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Suppose we have a nginx image got from Docker hub, and want to re-push it to Docker Hub under a personal account.&lt;/p&gt;

&lt;p&gt;Pull official image. If we do not specify a tag, the &lt;em&gt;latest&lt;/em&gt; image is pulled.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker pull nginx
Using default tag: latest
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Login to the personal account.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker login &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; myaccount
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Push to my personal account. If we do not specify a tag, the image is tagged to &lt;em&gt;latest&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker tag &amp;lt;nginx|sha256&amp;gt; myaccount/nginx

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker push myaccount/nginx
Using default tag: latest
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If we want to use a different registry rather than the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker.io&lt;/code&gt;, then add the registry to the new tag as well as follows.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker tag &amp;lt;nginx|sha256&amp;gt; myregistry.com:5000/myaccount/nginx

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker push myregistry.com:5000/myaccount/nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can assign mutiple tages to the image.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker tag &amp;lt;nginx|sha256&amp;gt; myaccount/nginx:2.0.0
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker push myaccount/nginx:2.0.0

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker tag &amp;lt;nginx|sha256&amp;gt; myaccount/nginx:2.0
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker push myaccount/nginx:2.0

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker tag &amp;lt;nginx|sha256&amp;gt; myaccount/nginx:2
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker push myaccount/nginx:2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can re-assign the &lt;em&gt;latest&lt;/em&gt; tag to a new version.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker tag myaccount/nginx:2.1.0 myaccount/nginx:latest
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker push myaccount/nginx:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the imange is multi-platform (e.g. AMD64 and ARM64) capable, we have to repeat the pull, tag and push for each platform via option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--platform&lt;/code&gt;. The more advanced tool &lt;a href=&quot;https://github.com/regclient/regclient/blob/main/docs/regctl.md&quot;&gt;regctl&lt;/a&gt; takes care of all platforms with just one command. Please read &lt;a href=&quot;https://stackoverflow.com/a/68576882/2336707&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://stackoverflow.com/a/68317548/2336707&quot;&gt;2&lt;/a&gt; and &lt;a href=&quot;https://stackoverflow.com/q/71470604/2336707&quot;&gt;3&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;regctl registry login
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;regctl registry config

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;regctl image manifest kong/kong-gateway:latest
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;regctl image inspect kong/kong-gateway:latest

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;regctl image manifest kong/kong-gateway:3.4.1.0

&lt;span class=&quot;c&quot;&gt;# pull, tag and push&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;regctl image copy kong/kong-gateway:3.4.1.0 kong/kong-gateway:latest
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;regctl image copy kong/kong-gateway:3.4.1.0-ubuntu kong/kong-gateway:latest-ubuntu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Apart from pushing to a registry, we can just &lt;a href=&quot;https://gist.github.com/outsinre/d2b58b289425fbdd2d0f0294f3fdf0c9&quot;&gt;share the image bundle&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker images &lt;span class=&quot;s1&quot;&gt;&apos;kong-wp&apos;&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker image save &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; kong-wp-3501.tar kong-wp:3.5.0.1

&lt;span class=&quot;c&quot;&gt;# for file transmission&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cJvf&lt;/span&gt; kong-wp-3501.tar.xz kong-wp-3501.tar
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xJvf&lt;/span&gt; kong-wp-3501.tar.xz

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker image load &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; kong-wp-3501.tar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pay attention that image bundle is different from the &lt;a href=&quot;https://github.com/opencontainers/runtime-spec/blob/v1.2.0/bundle.md&quot;&gt;OCI container bundle&lt;/a&gt;. See &lt;a href=&quot;https://stackoverflow.com/q/22655867/2336707&quot;&gt;What is the difference between save and export in Docker?&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;docker-compose&quot;&gt;Docker Compose&lt;/h1&gt;

&lt;p&gt;The compose project name by default is named after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PWD&lt;/code&gt;. The name of containers share the same prefix (i.e. name of the project).&lt;/p&gt;

&lt;p&gt;We can &lt;a href=&quot;https://docs.docker.com/compose/extends&quot;&gt;share compose configurations&lt;/a&gt; between files and/or projects by including other compose files or extending a service from from another service of another compose file. Check &quot;biji/archive/kong-dev-compose.yaml&quot;.&lt;/p&gt;

&lt;p&gt;When bind-mount a file, pay attention to provide the absolute path. Check &lt;a href=&quot;#data-share&quot;&gt;data share&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Docker Compose file, we can also use &lt;a href=&quot;#docker-build-dockerfile&quot;&gt;buildx&lt;/a&gt; to &lt;a href=&quot;https://stackoverflow.com/q/57840820/2336707&quot;&gt;build an image from Dockerfile&lt;/a&gt;. Alternatively, we can also &lt;a href=&quot;https://stackoverflow.com/q/30063907/2336707&quot;&gt;run multiple commands&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;/h1&gt;

&lt;p&gt;We can attach an ephemeral container to an existing container for troubleshooting purpose. The ephemeral container would share the target container&apos;s Linux namespaces.&lt;/p&gt;

&lt;p&gt;For example, to debug network issues, we can make use of &lt;a href=&quot;https://github.com/outsinre/netshoot&quot;&gt;netshoot&lt;/a&gt;. The netshoot container has a world of built-in network troubleshooting tools like &lt;em&gt;nmap&lt;/em&gt;, &lt;a href=&quot;http://www.tcpdump.org/tcpdump_man.html&quot;&gt;tcpdump&lt;/a&gt;, etc. We just need to attach the netshoot container to the target container&apos;s network namespace.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; netshoot &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--network&lt;/span&gt; container:&amp;lt;target-name|target-ID&amp;gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--mount&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bind&lt;/span&gt;,src&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;./data/,dst&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/data &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-itd&lt;/span&gt; nicolaka/netshoot

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; netshoot zsh

&lt;span class=&quot;c&quot;&gt;# capture packets of target container&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# tcpdump -i eth0 port 6379 -w /data/redis.pcap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For simple Linux utilities, we just &lt;a href=&quot;https://github.com/mirror/busybox&quot;&gt;busybox&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--net&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;container:opentelemetry-otel-collector-1 &lt;span class=&quot;nt&quot;&gt;--pid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;container:opentelemetry-otel-collector-1 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; busybox:1.36

/ &lt;span class=&quot;c&quot;&gt;# ps aux&lt;/span&gt;
PID   USER     TIME  COMMAND
    1 10001     1:12 /otelcol-contrib &lt;span class=&quot;nt&quot;&gt;--config&lt;/span&gt; /etc/otelcol-contrib/config.yaml
  212 root      0:00 sh
  218 root      0:00 ps aux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Policy Routing</title>
   <link href="/2018/03/26/policy-routing/"/>
   <updated>2018-03-26T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/03/26/policy-routing</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#policy-routing&quot; id=&quot;markdown-toc-policy-routing&quot;&gt;Policy Routing&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#terminology&quot; id=&quot;markdown-toc-terminology&quot;&gt;Terminology&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#principle&quot; id=&quot;markdown-toc-principle&quot;&gt;Principle&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#iproute2-tutorial&quot; id=&quot;markdown-toc-iproute2-tutorial&quot;&gt;Iproute2 Tutorial&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#launch-wireguard&quot; id=&quot;markdown-toc-launch-wireguard&quot;&gt;Launch WireGuard&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#relation-between-ipset-and-iptables&quot; id=&quot;markdown-toc-relation-between-ipset-and-iptables&quot;&gt;Relation Between Ipset and Iptables&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#create-ipset&quot; id=&quot;markdown-toc-create-ipset&quot;&gt;Create Ipset&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#iptables-set-mark-on-ipset&quot; id=&quot;markdown-toc-iptables-set-mark-on-ipset&quot;&gt;Iptables Set MARK On IPset&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#iproute2-rule-and-table-on-the-mark&quot; id=&quot;markdown-toc-iproute2-rule-and-table-on-the-mark&quot;&gt;Iproute2 Rule and Table On the MARK&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#set-up-dnsmasq-to-update-ipset&quot; id=&quot;markdown-toc-set-up-dnsmasq-to-update-ipset&quot;&gt;Set Up Dnsmasq to Update Ipset&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#configuration-files&quot; id=&quot;markdown-toc-configuration-files&quot;&gt;Configuration Files&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#configure-dnsmasq&quot; id=&quot;markdown-toc-configure-dnsmasq&quot;&gt;Configure Dnsmasq&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#update-blocked-domains-and-ipset&quot; id=&quot;markdown-toc-update-blocked-domains-and-ipset&quot;&gt;Update Blocked Domains and Ipset&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#iptables-nat-by-masquerade&quot; id=&quot;markdown-toc-iptables-nat-by-masquerade&quot;&gt;Iptables NAT by MASQUERADE&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#local-init-script&quot; id=&quot;markdown-toc-local-init-script&quot;&gt;Local Init Script&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#refs&quot; id=&quot;markdown-toc-refs&quot;&gt;Refs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This post is the successor of &lt;a href=&quot;/2018/03/20/wireguard/&quot;&gt;WireGuard&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;policy-routing&quot;&gt;Policy Routing&lt;/h1&gt;

&lt;p&gt;Policy routing could be accomplished based on bare IPs or domains. &lt;a href=&quot;/2018/03/20/wireguard/&quot;&gt;WireGuard&lt;/a&gt; post subscribes and updates IP sets periodically and adds relevant routes, which lacks flexibility as most IPs of the WireGuard set are not blocked by ISP. All traffic, by default, is routed to WireGuard except that of the CN set. The CN set can be called WireGuard blacklist. Another blacklist routing schema based on &lt;em&gt;dnsmasq&lt;/em&gt; is &lt;a href=&quot;https://github.com/felixonmars/dnsmasq-china-list&quot;&gt;dnsmasq-china-list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Rather, WireGuard whitelist maintains a much smaller IP set of blocked domains - blocked IP set. Only route traffic of blocked set to WireGuard table while leaving the rest to the &lt;em&gt;main&lt;/em&gt; table. All traffic, by default, is routed as usual.&lt;/p&gt;

&lt;p&gt;Usually, each IP set corresponds to a domain set. For instance, the blocked IP set mainly derives from the blocked domain set though ISP may decide to add on individual IPs to the list occasionally.&lt;/p&gt;

&lt;p&gt;In a nutshell, blacklist, whitelist and their sub-list can combine to realize policy routing as long decent routing rules and/or tables are configured. However, all the following configuration steps only involve whitelist set. To support other sets, just introduce extra routing tables and rules.&lt;/p&gt;

&lt;h1 id=&quot;terminology&quot;&gt;Terminology&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;A routing rule decides which routing table to look up.&lt;/li&gt;
  &lt;li&gt;A routing table is a collection of routes that refer to entries that direct packets.&lt;/li&gt;
  &lt;li&gt;Iproute2, Iptables, Ipset and Dnsmasq together do smart routing, namely policy routing.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;principle&quot;&gt;Principle&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Dnsmasq serves as a smart DNS service, maintaining domain sets: blocked domain set, non-blocked domain set, and sub-sets.&lt;/li&gt;
  &lt;li&gt;A relevant kernel Ipset is created in respond to each domain set.&lt;/li&gt;
  &lt;li&gt;Dnsmasq updates Ipsets on the fly.&lt;/li&gt;
  &lt;li&gt;Iptables set MARK on Ipsets.&lt;/li&gt;
  &lt;li&gt;Iproute2 rules and tables route packets based on Iptables MARK.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;iproute2-tutorial&quot;&gt;Iproute2 Tutorial&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;iproute2&lt;/em&gt; is successor of the ancient &lt;em&gt;ifconfig&lt;/em&gt;, providing userspace utilities for TCP / IP networking and traffic control in Linux, including routing, interfaces, tunnels, and traffic control.&lt;/li&gt;
  &lt;li&gt;Predefined identifiers (number and string name pairs) are located under &lt;em&gt;/etc/iproute2/&lt;/em&gt;. An item can be either referenced by its number or name. For example, table &lt;em&gt;254 main&lt;/em&gt; is where we update routes mostly.&lt;/li&gt;
  &lt;li&gt;A &lt;em&gt;metric&lt;/em&gt; or &lt;em&gt;preference&lt;/em&gt; is to &lt;a href=&quot;https://serverfault.com/a/648279&quot;&gt;set preference&lt;/a&gt; among routes or rules with equal specificity.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Check routing rules and routes:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# man [ ip-route | ip-rule ]&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip rule list&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip route [ list table main ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create routing rules and tables:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip -4 rule add not fwmark 0xca6c pref 10 table 0xca6c&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip rule add to 223.255.236.0/22 pref 20 table 254&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;New routing tables are created on demand (i.e. not exist)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;pref&lt;/em&gt; specifies rule preference.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add routes:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip route add 1.0.1.0/24 via 192.168.0.1 dev wlan0 proto dhcp src 192.168.0.100 metric 30&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip route add 8.8.8.8/32 dev wlan0 pref 40&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;via&lt;/em&gt; means the gateway.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;dev&lt;/em&gt; followed by the outgoing interface.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;pref&lt;/em&gt; and &lt;em&gt;metric&lt;/em&gt; are the same thing: priority/preference.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;launch-wireguard&quot;&gt;Launch WireGuard&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;wg-quick&lt;/em&gt; generates Iproute2 rules and tables to route all traffic through WireGuard except that of &lt;em&gt;endpoint&lt;/em&gt;. To support different sets, we should carefully configure Iproute2.&lt;/p&gt;

&lt;p&gt;The following setup is an example of WireGuard whitelist set. In spite of &lt;em&gt;wg-quick&lt;/em&gt; method in prior post, manual configuration is preferred in this post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;01-wg0.start&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

ip &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;add wg0 mtu 1420 &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;wireguard
ip &lt;span class=&quot;nb&quot;&gt;link set &lt;/span&gt;dev wg0 up
ip addr add 10.0.0.2/24 dev wg0
wg setconf wg0 /etc/wireguard/wg0.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The script is updated as this post progresses. Similarto the preceding post, set this as &lt;em&gt;local.d&lt;/em&gt; Init service.&lt;/p&gt;

&lt;h1 id=&quot;relation-between-ipset-and-iptables&quot;&gt;Relation Between Ipset and Iptables&lt;/h1&gt;

&lt;p&gt;&quot;IP set&quot; is a framework inside the Linux kernel, which can be administered by userspace utility &lt;em&gt;ipset&lt;/em&gt;. Depending on the type, an IP set may store IP addresses, networks, (TCP/UDP) port numbers, MAC addresses, interface names or combinations of them in a way, which ensures lightning speed when matching an entry against a set.&lt;/p&gt;

&lt;p&gt;Linux kernel must enable IP set and then &lt;em&gt;net-firewall/ipset&lt;/em&gt; is required. IP set can be enabled by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP_SET&lt;/code&gt; and relevant sub-options such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP_SET_HASH_IP&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP_SET_HASH_NET&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP_SET_LIST_SET&lt;/code&gt;. Alternatively, enable &lt;em&gt;USE=modules&lt;/em&gt; of &lt;em&gt;net-firewall/ipset&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;An IP set based on blocked domains will be updated on the fly. To make use of the IP set, please enable Netfilter (Iptables) SET match extension (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NETFILTER_XT_SET&lt;/code&gt;) and MARK target (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NETFILTER_XT_MARK&lt;/code&gt;).&lt;/p&gt;

&lt;h1 id=&quot;create-ipset&quot;&gt;Create Ipset&lt;/h1&gt;

&lt;p&gt;Installation:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# USE=modules is not enabled.&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# emerge -avt ipset&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# rc-update add ipset default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can create kernel IP set with &lt;em&gt;ipset&lt;/em&gt; command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# ipset -! create gfwlist hash:net&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ipset list [ gfwlist ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, &lt;em&gt;ipset&lt;/em&gt; will throw an error errors when creating sets or adding elements that do exist or when deleting elements that don&apos;t exist. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-!, -exist&lt;/code&gt; will ignore the error.&lt;/p&gt;

&lt;p&gt;An IP set called &apos;gfwlist&apos; is created but it&apos;s an empty set without any IP elements. Let&apos;s add a few entries:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# ipset -! add gfwlist 8.8.8.8; ipset list&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ipset -! add gfwlist 8.8.4.4; ipset list&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ipset -! del gfwlist 8.8.4.4; ipset list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We want all IPs associated with blocked domains be added to &apos;gfwlist&apos; set, which is impossible without the help of &lt;em&gt;dnsmasq&lt;/em&gt; as IPs vary frequently. That is to say, &apos;gfwlist&apos; set should be updated frequently as well. Especially, we want to add clean DNS servers (i.e. &lt;em&gt;8.8.8.8&lt;/em&gt;) to &apos;gfwlist&apos; at first.&lt;/p&gt;

&lt;p&gt;Save current state&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# rc-service ipset save&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ipset save &amp;gt; /var/lib/ipset/rules-save&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Launch&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# rc-service ipset start; ipset list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, &lt;em&gt;ipset&lt;/em&gt; service will load prior set on startup while save current set on stop.&lt;/p&gt;

&lt;h1 id=&quot;iptables-set-mark-on-ipset&quot;&gt;Iptables Set MARK On IPset&lt;/h1&gt;

&lt;p&gt;Having Kernel IP set created and preliminarily updated, we assign MARK target to &apos;gfwlist&apos; set with Iptables.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Create a new chain&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -t mangle -N GFWLIST&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# OUTPUT to GFWLIST&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -t mangle -C OUTPUT -j GFWLIST || iptables -t mangle -A OUTPUT -j GFWLIST&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Set mark 51820 on packets of &apos;gfwlist&apos; IP set.&lt;/span&gt;
root@TUX ~ &lt;span class=&quot;c&quot;&gt;# iptables -t mangle -A GFWLIST -m set --match-set gfwlist dst -j MARK --set-mark 51820&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Only required when peer A serves as a gateway as well.&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -t mangle -C [ FORWARD | PREROUTING ]  -j GFWLIST || iptables -t mangle -A [ FORWARD | PREROUTING ] -j GFWLIST (opt)&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# sysctl -w net.ipv4.ip_forward=1 (opt)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;mangle&lt;/em&gt; table is used for specialized packet alteration.&lt;/li&gt;
  &lt;li&gt;A new chain GFWLIST is created for &apos;gfwlist&apos; IP set for better isolation.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-C&lt;/code&gt; checks whether a rule exists or not.&lt;/li&gt;
  &lt;li&gt;When a packet hits FORWARD chain, it has been routed already. Instead, PREROUTING is hit before routing.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;iproute2-rule-and-table-on-the-mark&quot;&gt;Iproute2 Rule and Table On the MARK&lt;/h1&gt;

&lt;p&gt;Now that &apos;gfwlist&apos; IP set is marked by Iptables, we will create a routing rule and table for the mark. Before that we can define a string identifier for the table.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Number and name identifier&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# echo &quot;51820	gfwlist&quot; &amp;gt;&amp;gt; /etc/iproute2/rt_tables&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Create routing rule and table: traffic of &apos;gfwlist&apos; set is routed through &apos;gfwlist&apos; table&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip rule add fwmark 51820 table gfwlist&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Set routing table: going out through WireGuard.&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip route add default dev wg0 table gfwlist&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Identifier of Iproute2 table (&lt;em&gt;51820 gfwlist&lt;/em&gt;) needn&apos;t to be the same as that of Iptables mark (51820).&lt;/p&gt;

&lt;p&gt;Recall that, we&apos;ve manually added &lt;em&gt;8.8.8.8&lt;/em&gt; to &apos;gfwlist&apos; set. Instead, add a new route in the &lt;em&gt;main&lt;/em&gt; table though it is somewhat less mart.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip route add 8.8.8.8 dev wg0 table main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;01-wg0.start&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Bring up WireGuard link&lt;/span&gt;
ip &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;add wg0 &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;wireguard
ip &lt;span class=&quot;nb&quot;&gt;link set &lt;/span&gt;mtu 1420 dev wg0
ip addr add 10.0.0.2/24 dev wg0
wg setconf wg0 /etc/wireguard/wg0_wg.conf
ip &lt;span class=&quot;nb&quot;&gt;link set &lt;/span&gt;up dev wg0

&lt;span class=&quot;c&quot;&gt;# To route server&apos;s internal IP&lt;/span&gt;
ip route add 192.168.58.0/24 dev wg0
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#ip rule add 192.168.58.0/24 table gfwlist&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# To route &apos;gfwlist&apos; IP set&lt;/span&gt;
ip rule add fwmark 51820 table gfwlist
ip route add default dev wg0 table gfwlist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;In this case, the internal IP of client and server fall into different network block, namely &lt;em&gt;10.0.0.0/24&lt;/em&gt; and &lt;em&gt;192.168.58.0/24&lt;/em&gt;. As mentioned in the prior post, explicit route should be added on both sides.&lt;/li&gt;
  &lt;li&gt;This is almost the final version. As &lt;em&gt;192.168.58.0/24&lt;/em&gt; is an LAN block, we&apos;d better leave it in the main table.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;set-up-dnsmasq-to-update-ipset&quot;&gt;Set Up Dnsmasq to Update Ipset&lt;/h1&gt;

&lt;p&gt;The key success of policy routing depends on the accuracy of &apos;gfwlist&apos; IP set. So far, it is almost empty besides a few clean DNS elements. This is where Dnsmasq comes to help!&lt;/p&gt;

&lt;p&gt;Dnsmasq provides Domain Name System (DNS) forwarder, Dynamic Host Configuration Protocol (DHCP) server, router advertisement and network boot features for small computer networks, created as free software. Here, we use Dnsmasq to provide smart DNS service locally and update &apos;gfwlist&apos; IP set on demand.&lt;/p&gt;

&lt;p&gt;Installation:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# echo &apos;net-dns/dnsmasq -dhcp dnssec&apos; &amp;gt; /etc/portage/package.use/dnsmasq&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# emerge -avt net-dns/dnsmasq&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# rc-update add dnsmasq default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Dnsmasq is presented with predefined blocked domains. Dnsmasq resolves them into IPs upon receiving DNS query.&lt;/li&gt;
  &lt;li&gt;Dnsmasq now has builtin Ipset support and the resolved IPs can be added to &apos;gfwlist&apos; IP set automatically.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;configuration-files&quot;&gt;Configuration Files&lt;/h2&gt;

&lt;p&gt;All options within the default &lt;em&gt;/etc/dnsmasq.conf&lt;/em&gt; are commented out. We can leave that as a reference but load configuration from separate files.&lt;/p&gt;

&lt;p&gt;Firstly, we add a command line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--conf-dir&lt;/code&gt; to &lt;em&gt;/etc/conf.d/dnsmasq&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Loads all files with the suffix .conf; ignore ther others

DNSMASQ_OPTS=&quot;--user=dnsmasq --group=dnsmasq --conf-dir=/etc/dnsmasq.d/,*.conf&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A better idea is appending that option to &lt;em&gt;/etc/dnsmasq.conf&lt;/em&gt; so that &lt;em&gt;resolvconf&lt;/em&gt; will pick it up:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# echo &amp;gt;&amp;gt; /etc/dnsmasq.conf&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# echo &apos;conf-dir=/etc/dnsmasq.d/,*.conf&apos; &amp;gt;&amp;gt; /etc/dnsmasq.conf&lt;/span&gt;

root@tux ~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /etc/dnsmasq.d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;configure-dnsmasq&quot;&gt;Configure Dnsmasq&lt;/h2&gt;

&lt;p&gt;Dnsmasq will be the sole DNS server in the system in the following set up. Please prevent &lt;em&gt;dhcpcd&lt;/em&gt; from overriding &lt;em&gt;/etc/resolv.conf&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/dhcpcd.conf

nohook resolv.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then we create &lt;em&gt;/etc/dnsmasq.d/dns.conf&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# lo only
bind-interfaces
listen-address=127.0.0.1
# lo and eth2
#bind-dynamic
#interface=eth2

# DNS port
port=53

# dbus
enable-dbus

# dnssec
dnssec
conf-file=/usr/share/dnsmasq/trust-anchors.conf
#dnssec-check-unsigned

# Upstream nameservers (i.e. from ISP)
resolv-file=/etc/dnsmasq.d/resolv.dnsmasq

# hosts addon
addn-hosts=/etc/dnsmasq.d/hosts.dnsmasq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;dnssec-check-unsigned&lt;/em&gt; would drop DNS replies if upstream DNS servers does not support DNSSEC. Up to now, I cannot find any ISP DNS servers with DNSSEC support. Hence, &lt;em&gt;dnssec-check-unsigned&lt;/em&gt; cannot resolve unblocked domains from upstream nameservers.&lt;/p&gt;

&lt;p&gt;If we want Dnsmasq to support newly created interface on demand, we can use &lt;em&gt;bind-dynamic&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# lo only
#bind-interfaces
#listen-address=127.0.0.1

# lo and eth2
bind-dynamic
interface=eth2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This would implicitly include &lt;em&gt;lo&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;update-blocked-domains-and-ipset&quot;&gt;Update Blocked Domains and Ipset&lt;/h2&gt;

&lt;p&gt;As discussed earlier, we should firstly fuel Dnsmasq with blocked domains. Here is a predefined and updated blocked domain list: &lt;a href=&quot;https://github.com/cokebar/gfwlist2dnsmasq&quot;&gt;gfwlist2dnsmasq&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# git clone --depth=1 https://github.com/cokebar/gfwlist2dnsmasq&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ./gfwlist2dnsmasq.sh -h&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ./gfwlist2dnsmasq.sh -d 8.8.8.8 -p 53 -s gfwlist -o /etc/dnsmasq.d/gfwlist.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The accompanying script &lt;em&gt;gfwlist2dnsmasq.sh&lt;/em&gt; automatically fetches newest blocked domains and generates corresponding Dnsmasq configuration file without user intervention. Then, set &lt;em&gt;cron&lt;/em&gt; job to update &apos;gfwlist&apos; set periodically:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

/opt/gfwlist2dnsmasq/gfwlist2dnsmasq.sh &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; 8.8.8.8 &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 53 &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; gfwlist &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; /etc/dnsmasq.d/gfwlist.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A new &lt;em&gt;dnsmasq&lt;/em&gt; configuration file which only contains &lt;em&gt;server&lt;/em&gt; and &lt;em&gt;ipset&lt;/em&gt; pairs like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;server=/030buy.com/8.8.8.8#53
ipset=/030buy.com/gfwlist

server=/0rz.tw/8.8.8.8#53
ipset=/0rz.tw/gfwlist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;dnsmasq&lt;/em&gt; resolves &lt;em&gt;030buy.com&lt;/em&gt; and &lt;em&gt;0rz.tw&lt;/em&gt; through &lt;em&gt;8.8.8.8:53&lt;/em&gt;, which would be routed through WireGuard.&lt;/p&gt;

&lt;p&gt;So far, Dnsmasq is done! However, we can&apos;t even &lt;em&gt;dig&lt;/em&gt; blocked domains.&lt;/p&gt;

&lt;h1 id=&quot;iptables-nat-by-masquerade&quot;&gt;Iptables NAT by &lt;a href=&quot;https://serverfault.com/q/248841&quot;&gt;MASQUERADE&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;To be clear, we should enable MASQUERADE or SNAT as post &lt;a href=&quot;/2017/12/29/linux-as-gateway-router/&quot;&gt;linux as gateway router&lt;/a&gt; writes. Please be noted policy routing on the client side do not require IP forwarding or Iptables FORWARD.&lt;/p&gt;

&lt;p&gt;Please refer to the Netfilter flow chart:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://inai.de/images/nf-packet-flow.svg&quot; alt=&quot;Packet flow in Netfilter and General Networking&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Locally generated packets are routed twice before going out. The first routing is exercized before entering the Iptables flow as &lt;em&gt;routing decision&lt;/em&gt;. The second routing happens within the flow as &quot;reroute check&quot;.&lt;/li&gt;
  &lt;li&gt;Routing will not modify any field of packet!&lt;/li&gt;
  &lt;li&gt;We can examine Iptables logs at different steps of the flow chart.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let us have a look at Iptables log on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t nat OUTPUT&lt;/code&gt; chain:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -t nat -A OUTPUT -m mark --mark 51820 -j LOG --log-level debug&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# dmesg -w&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# dig www.google.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is an log sample:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[20083.739224] IN= OUT=wlan0 SRC=192.168.0.100 DST=8.8.8.8 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=10293 DF PROTO=UDP SPT=38374 DPT=53 LEN=40 MARK=0xca6c 
[20083.739408] IN= OUT=wlan0 SRC=192.168.0.100 DST=23.45.67.89 LEN=124 TOS=0x00 PREC=0x00 TTL=64 ID=14878 PROTO=UDP SPT=12345 DPT=54321 LEN=104 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;The first line. The packet DST is &lt;em&gt;8.8.8.8&lt;/em&gt; with MARK as 0xca6c, which means this is the original DNS query packet. The &lt;em&gt;routing decision&lt;/em&gt; successfully matched the &lt;em&gt;default&lt;/em&gt; route in &lt;em&gt;main&lt;/em&gt; table. Afterwards, the packet was set MARK by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t mangle OUTPUT&lt;/code&gt; chain. Then &lt;em&gt;reroute check&lt;/em&gt; routed the packet against &lt;em&gt;gfwlist&lt;/em&gt; rule and table according to the the MARK. This packet went to &lt;em&gt;wg0&lt;/em&gt; and we get the log at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t nat OUTPUT&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The second line. The original DNS packet was encapsulated into a new WireGuard UDP with DST &lt;em&gt;23.45.67.89&lt;/em&gt; (server&apos;s public IP). The new packet was then sent to server.&lt;/li&gt;
  &lt;li&gt;IN is empty as local generated packets do have associated any input interface.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As mentioned earlier, routing does not change a packet. However, the OUT and SRC of the first packet should be changed to &lt;em&gt;wg0&lt;/em&gt; and &lt;em&gt;10.0.0.1&lt;/em&gt; (internal IP of client A) after &lt;em&gt;reroute check&lt;/em&gt; and before encapsulation by WireGuard. It looks as though the packet were generated by &lt;em&gt;wg0&lt;/em&gt;. This can be achieved by Iptables NAT. That is to say, the first packet should be transferred from:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Before &apos;reroute check&apos;.
OUT=wlan0 SRC=192.168.0.100 DST=8.8.8.8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# After &apos;reroute check&apos; and before encapsulation.
OUT=wg0 SRC=10.0.0.1 DST=8.8.8.8 MARK=0xca6c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Without Iptables NAT support, reply packets from the server would be abandoned. Suppose the VPN server receives the second line and replies with DST &lt;em&gt;192.168.0.100&lt;/em&gt; and DPT 12345. The reply packet is then passed to &lt;em&gt;wg0&lt;/em&gt; in accord with DPT where WireGuard listens for traffic. Upon receiving the packet, &lt;em&gt;wg0&lt;/em&gt; abandons it immediately as DST does not match &lt;em&gt;10.0.0.1&lt;/em&gt; - malformed packet.&lt;/p&gt;

&lt;p&gt;Iptables NAT usually is executed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t nat POSTROUTING&lt;/code&gt; chain with MASQUERADE or SNAT target.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -t nat -A POSTROUTING -o wg0 -m mark --mark 51820 -j SNAT --to-source 10.0.0.1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -t nat -A POSTROUTING -o wg0 -m mark --mark 51820 -j MASQUERADE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can also examine Iptable logs in other tables and chains in accordance with the figure above. For example, before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t mangle OUTPUT&lt;/code&gt; the first packet is not marked. After &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t nat POSTROUTING&lt;/code&gt;, the first packet is modified accordingly.&lt;/p&gt;

&lt;p&gt;Up to now, policy routing with WireGuard whitelist (&apos;gfwlist&apos; Ipset) is done! We can add extra Ipsets and relevant Iproute2 routing rules and tables. Of course, new Ipsets should also be marked by Iptables.&lt;/p&gt;

&lt;h1 id=&quot;local-init-script&quot;&gt;Local Init Script&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;01-wg0.start&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Bring up WireGuard link&lt;/span&gt;
ip &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;add wg0 mtu 1420 &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;wireguard
ip &lt;span class=&quot;nb&quot;&gt;link set &lt;/span&gt;dev wg0 up
ip addr add 10.0.0.2/24 dev wg0
wg setconf wg0 /etc/wireguard/wg0.conf

&lt;span class=&quot;c&quot;&gt;# ip route&lt;/span&gt;
ip route add 192.168.58.0/24 dev wg0
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#ip rule add 192.168.58.0/24 table gfwlist&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# ip rule&lt;/span&gt;
ip rule add fwmark 51820 table gfwlist
ip route add default dev wg0 table gfwlist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;01-wg0.stop&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# del gfwlist table&lt;/span&gt;
ip rule del table gfwlist

&lt;span class=&quot;c&quot;&gt;# ip route&lt;/span&gt;
ip route del 192.168.58.0/24 dev wg0
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#ip rule del 192.168.58.0/24 table gfwlist&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Remove WireGuard&lt;/span&gt;
ip &lt;span class=&quot;nb&quot;&gt;link &lt;/span&gt;del dev wg0 &lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;wireguard
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The VPN Proxy section in prior post, all traffic is routed through &lt;em&gt;wg0&lt;/em&gt;. So it presents multiple methods (i.e. &lt;em&gt;suppress_prefixlength 0&lt;/em&gt; from &lt;em&gt;wg-quick&lt;/em&gt;) such that traffic to the server&apos;s public IP is routed through the &lt;em&gt;main&lt;/em&gt; table instead.&lt;/p&gt;

&lt;p&gt;The scripts above do not require any of those methods as &apos;gfwlist&apos; does not include that IP. More specifically, as long as Ipset is used, we can put the IP into a set (i.e. CN set) routed by &lt;em&gt;main&lt;/em&gt; table. At the same time, make sure it is not covered by Ipsets routed through &lt;em&gt;wg0&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://harveyhu2012.webcrow.jp/wordpress/?p=184&quot;&gt;路由器自动分流科学上网原理和实现方式研究&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cnblogs.com/weifeng1463/p/6796140.html&quot;&gt;Openwrt上使用dnsmasq和ipset实现域名分流&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.sorz.org/p/openwrt-outwall/&quot;&gt;OpenWrt VPN 按域名路由&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zohead.com/archives/openwrt-openvpn-ipset/&quot;&gt;OpenWRT实现OpenVPN按ipset自动分流&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bigeagle.me/2016/02/ipset-policy-routing/&quot;&gt;使用 dnsmasq 和 ipset 的策略路由&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>WireGuard</title>
   <link href="/2018/03/20/wireguard/"/>
   <updated>2018-03-20T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/03/20/wireguard</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#preamble&quot; id=&quot;markdown-toc-preamble&quot;&gt;Preamble&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#schema&quot; id=&quot;markdown-toc-schema&quot;&gt;Schema&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#create-wireguard-interface&quot; id=&quot;markdown-toc-create-wireguard-interface&quot;&gt;Create WireGuard Interface&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#assign-wireguard-ip&quot; id=&quot;markdown-toc-assign-wireguard-ip&quot;&gt;Assign WireGuard IP&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wireguard-key-pair&quot; id=&quot;markdown-toc-wireguard-key-pair&quot;&gt;WireGuard Key pair&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configure-wireguard-interface&quot; id=&quot;markdown-toc-configure-wireguard-interface&quot;&gt;Configure WireGuard Interface&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#persistent-configuration&quot; id=&quot;markdown-toc-persistent-configuration&quot;&gt;Persistent Configuration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wireguard-link-up&quot; id=&quot;markdown-toc-wireguard-link-up&quot;&gt;WireGuard Link Up&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#check-wireguard-route&quot; id=&quot;markdown-toc-check-wireguard-route&quot;&gt;Check WireGuard Route&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#allow-endpoint-in-iptables&quot; id=&quot;markdown-toc-allow-endpoint-in-iptables&quot;&gt;Allow endpoint in Iptables&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#final-ping&quot; id=&quot;markdown-toc-final-ping&quot;&gt;Final ping&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#set-server-b-as-a-gateway&quot; id=&quot;markdown-toc-set-server-b-as-a-gateway&quot;&gt;Set Server B as a Gateway&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#ip-forwarding&quot; id=&quot;markdown-toc-ip-forwarding&quot;&gt;IP Forwarding&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#proxy-arp-on-server-side&quot; id=&quot;markdown-toc-proxy-arp-on-server-side&quot;&gt;Proxy ARP on Server Side&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#allow-ip-forwarding-through-iptables&quot; id=&quot;markdown-toc-allow-ip-forwarding-through-iptables&quot;&gt;Allow IP Forwarding through Iptables&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#set-up-iptables-nat&quot; id=&quot;markdown-toc-set-up-iptables-nat&quot;&gt;Set up Iptables NAT&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#lan-access&quot; id=&quot;markdown-toc-lan-access&quot;&gt;LAN Access&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#vpn-proxy&quot; id=&quot;markdown-toc-vpn-proxy&quot;&gt;VPN Proxy&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#allowed-ips-catch-all&quot; id=&quot;markdown-toc-allowed-ips-catch-all&quot;&gt;&lt;em&gt;allowed-ips&lt;/em&gt; Catch All&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#update-client-a-routes&quot; id=&quot;markdown-toc-update-client-a-routes&quot;&gt;Update Client A Routes&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#replace-the-default-route&quot; id=&quot;markdown-toc-replace-the-default-route&quot;&gt;Replace the default Route&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#override-the-default-route&quot; id=&quot;markdown-toc-override-the-default-route&quot;&gt;Override the default Route&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#rule-based-routing&quot; id=&quot;markdown-toc-rule-based-routing&quot;&gt;Rule-based routing&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#wg-quick-method&quot; id=&quot;markdown-toc-wg-quick-method&quot;&gt;&lt;em&gt;wg-quick&lt;/em&gt; method&lt;/a&gt;            &lt;ol&gt;
              &lt;li&gt;&lt;a href=&quot;#suppress_prefixlength&quot; id=&quot;markdown-toc-suppress_prefixlength&quot;&gt;suppress_prefixlength&lt;/a&gt;&lt;/li&gt;
            &lt;/ol&gt;
          &lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#procedures-illustrated&quot; id=&quot;markdown-toc-procedures-illustrated&quot;&gt;Procedures Illustrated&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#policy-routing-based-on-bare-ips&quot; id=&quot;markdown-toc-policy-routing-based-on-bare-ips&quot;&gt;Policy Routing Based on Bare IPs&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#ip-set&quot; id=&quot;markdown-toc-ip-set&quot;&gt;IP set&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#static-route-method&quot; id=&quot;markdown-toc-static-route-method&quot;&gt;Static Route Method&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#geoip-method&quot; id=&quot;markdown-toc-geoip-method&quot;&gt;Geoip method&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#improve-local-dns-servers&quot; id=&quot;markdown-toc-improve-local-dns-servers&quot;&gt;Improve Local DNS Servers&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wg-quick&quot; id=&quot;markdown-toc-wg-quick&quot;&gt;wg-quick&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#booting&quot; id=&quot;markdown-toc-booting&quot;&gt;Booting&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#gentoo-wg-quick&quot; id=&quot;markdown-toc-gentoo-wg-quick&quot;&gt;Gentoo wg-quick&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#systemd-wg-quick&quot; id=&quot;markdown-toc-systemd-wg-quick&quot;&gt;systemd wg-quick&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#cron-job&quot; id=&quot;markdown-toc-cron-job&quot;&gt;cron job&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#notes&quot; id=&quot;markdown-toc-notes&quot;&gt;Notes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#reference&quot; id=&quot;markdown-toc-reference&quot;&gt;Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;preamble&quot;&gt;Preamble&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://www.wireguard.com/&quot;&gt;WireGuard&lt;/a&gt; claim to utilizes state-of-the-art cryptography (Noise protocol framework, Curve25519, ChaCha20, Poly1305, BLAKE2, SipHash24, HKDF etc.) while provide a simple construction.&lt;/p&gt;

&lt;p&gt;It requires a virtual network interface and an IP assigned. The interface is associated with a public/private key pair of which the public part serves as the identity within WireGuard network. WireGuard encapsulates IP packets (application data payload) over UDP and forwards packets based on Cryptokey Routing- a UDP VPN.&lt;/p&gt;

&lt;p&gt;Originally, WireGuard is integrated into Linux kernel (module or built-in tree). Nowadays, it&apos;s under heady development to be cross-platform and widely deployable. The 6th reference (NAT-to-NAT VPN with WireGuard) is worth reading.&lt;/p&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;p&gt;To install as an external module:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# emerge -avt wireguard openresolv&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# modinfo wireguard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Optionally, we can build WireGuard as an &lt;a href=&quot;https://www.wireguard.com/install/&quot;&gt;internal kernel module or as built-in&lt;/a&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;module-src&lt;/code&gt; USE.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;openresolv&lt;/em&gt; is needed if &lt;em&gt;wireguard&lt;/em&gt; (by &lt;em&gt;wg-quick&lt;/em&gt;) defines custom DNS.&lt;/p&gt;

&lt;h1 id=&quot;schema&quot;&gt;Schema&lt;/h1&gt;

&lt;p&gt;Before everything else, we should grasp the conceptual overview.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Peer&lt;/th&gt;
      &lt;th&gt;Client A&lt;/th&gt;
      &lt;th&gt;Server B&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;External IP&lt;/td&gt;
      &lt;td&gt;192.168.0.123&lt;/td&gt;
      &lt;td&gt;23.45.67.89&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;UDP port&lt;/td&gt;
      &lt;td&gt;48574&lt;/td&gt;
      &lt;td&gt;39814&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Internal IP&lt;/td&gt;
      &lt;td&gt;10.0.0.1/24&lt;/td&gt;
      &lt;td&gt;10.0.0.2/24&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;External IP (i.e. &lt;em&gt;eth0&lt;/em&gt;) is given by ISP or Wi-Fi router, without which you cannot reach the Internet. On the other hand, internal IP manually assigned to WireGuard interface is privately valid only within WireGuard network. UDP port associated with external IP is where WireGuard service listens for traffic.&lt;/p&gt;

&lt;p&gt;WireGuard does not assume server side or client side. The peer initiates connections is regarded as the client. For terminology consistency, peer B with public IP is the server while peer A censorshipped by ISP is the client. In this post, peer A sites behind a Wi-Fi router (NAT).&lt;/p&gt;

&lt;p&gt;Clearly, Peer A, on the initiative, opens connections to peer B establishing a point-to-point tunnel. With a few arguments adjustment, peer A reaches the whole remote block &lt;em&gt;10.0.0.0/24&lt;/em&gt; such as devices without WireGuard but IP falling into that range. A step further, peer A can route all its traffic through B to the Internet.&lt;/p&gt;

&lt;p&gt;Firstly, we start off by establishing a point-to-point link. Without explicit notice, the configuration steps should be executed on both sides.&lt;/p&gt;

&lt;h1 id=&quot;create-wireguard-interface&quot;&gt;Create WireGuard Interface&lt;/h1&gt;

&lt;p&gt;Create Wireguard interface with Iproute2, which automatically loads &lt;em&gt;wireguard&lt;/em&gt; module:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# modprobe -v wireguard (opt)&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip link add dev wg0 type wireguard&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;assign-wireguard-ip&quot;&gt;Assign WireGuard IP&lt;/h2&gt;

&lt;p&gt;Unless you have a really good reason, please assign internal IPs within the same subnet for client and server sides. Otherwise, you want extra routes on both sides.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip addr add 10.0.0.1/24 dev wg0&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip addr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;wireguard-key-pair&quot;&gt;WireGuard Key pair&lt;/h1&gt;

&lt;p&gt;Permission:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;umask &lt;/span&gt;077
root@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /etc/wireguard/keys&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /etc/wireguard/keys/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Private/public keys:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wg genkey &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; private-key&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;private-key
root@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wg pubkey &amp;lt; private-key &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; public-key&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;public-key
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Optionally, this can be done all at once:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wg genkey | &lt;span class=&quot;nb&quot;&gt;tee &lt;/span&gt;private-key | wg pubkey &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; public-key
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;configure-wireguard-interface&quot;&gt;Configure WireGuard Interface&lt;/h1&gt;

&lt;p&gt;Arguments can be loaded from file.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# wg setconf wg0 /etc/wireguard/wg0.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# wg set wg0 listen-port 48574 private-key /etc/wireguard/private-key&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# wg set wg0 peer &amp;lt;public-key of peer&amp;gt; [persistent-keepalive 25] [endpoint 23.45.67.89:39814] allowed-ips 10.0.0.2/32,10.0.100.2/24&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# wg [showconf wg0]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Public key should be &lt;em&gt;base64&lt;/em&gt; format like &lt;em&gt;V7g3kxzLATJ6edBybau1IrE3FOgLHajxxFfMZ+QOUyE=&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To traverse NAT or firewall, &lt;em&gt;persistent-keepalive&lt;/em&gt; is a must for peers behind NAT or firewall.&lt;/p&gt;

    &lt;p&gt;For instance, client A sites behind NAT (i.e. Wi-Fi router), &lt;em&gt;persistent-keepalive&lt;/em&gt; sends packets to other peers periodically to keep NAT mapping open.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;endpoint&lt;/em&gt; is the remote peer&apos;s external yet public IP and UDP port.&lt;/p&gt;

    &lt;p&gt;Only client sides that makes the initial connection require &lt;em&gt;endpoint&lt;/em&gt;. It&apos;s recommended to leave this argument out when setting server sides because they update &lt;em&gt;endpoint&lt;/em&gt; values by examining from where correctly authenticated packets originates. Meanwhile, clients behind NAT or dial-up do not even have fixed public IPs.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;allowed-ips&lt;/em&gt; is a list of comma-separated IP ranges to which WireGuard traffic can be sent and from which WireGuard traffic can be recevied.&lt;/p&gt;

    &lt;p&gt;For a simple point-to-point connection, it should be a peer&apos;s internal IP. To reach the whole LAN network, we set it to &lt;em&gt;10.0.0.0/24&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;The catch-all &lt;em&gt;0.0.0.0/0&lt;/em&gt; and &lt;em&gt;::/0&lt;/em&gt; match all IPv4/6 addresses, routing all local traffic through WireGuard. This is useful if we want to set up transparent proxy on client sides.&lt;/p&gt;

    &lt;p&gt;Whatever network ranges we choose, the peer&apos;s internal IP must be covered.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Multiple peers can be added.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;persistent-configuration&quot;&gt;Persistent Configuration&lt;/h1&gt;

&lt;p&gt;Setup above is versatile across reboots. To be permanent, arguments can be loaded from file on boot. By default, configuration file locates under &lt;em&gt;/etc/wireguard/&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To save and load configuration:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# wg showconf wg0 &amp;gt; /etc/wireguard/wg0.conf&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# wg setconf wg0 /etc/wireguard/wg0.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is an example of point-to-point VPN link:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Interface]
ListenPort = 48574
PrivateKey = EOpLmUJ08uwH2z2NpBwJ2upWzB5Tn36nhQvlXccAFnk

[Peer]
PublicKey = 7nXZYaqyXuVdW0RwHauMJuW81axAM9hSavY9JIJsZFU=
AllowedIPs = 10.0.0.2/32
Endpoint = 23.45.67.89:39814
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;wireguard-link-up&quot;&gt;WireGuard Link Up&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip link set up dev wg0&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip link; ip addr&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ss -npelu&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A WireGuard UDP socket is created.&lt;/p&gt;

&lt;h1 id=&quot;check-wireguard-route&quot;&gt;Check WireGuard Route&lt;/h1&gt;

&lt;p&gt;When internal IP is assigned, a system route is added automatically for that IP range like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;10.0.0.0/24 dev wg0 proto kernel scope link src 10.0.0.1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a remote peer&apos;s internal IP (be covered by &lt;em&gt;allowed-ips&lt;/em&gt;) belongs to a different subnet (i.e. B&apos;s is &lt;em&gt;192.168.58.1/32&lt;/em&gt;), they cannot connect to each other unless a special route is created on both sides.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# client A&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip route add 192.168.58.0/24 dev wg0 proto kernel scope link&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# server B&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip route add 10.0.0.0/24 dev wg0 proto kernel scope link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For strict control, the range could be narrowed down to the internal IP address like:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# client A&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# ip route add 192.168.58.1/32 dev wg0 proto kernel scope link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;allow-endpoint-in-iptables&quot;&gt;Allow endpoint in Iptables&lt;/h1&gt;

&lt;p&gt;Please make sure the &lt;em&gt;endpoint&lt;/em&gt; is accepted by firewall.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -A OUTPUT -d 23.45.67.89/32 -p udp -m udp --dport 39814 -m conntrack --ctstate NEW -j ACCEPT&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -A INPUT -s 23.45.67.89/32 -p udp -m udp --sport 39814 -m conntrack --ctstate NEW -j ACCEPT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;final-ping&quot;&gt;Final ping&lt;/h2&gt;

&lt;p&gt;By far, a point-to-point link is established. Peer A and B can communicate with each other.&lt;/p&gt;

&lt;h1 id=&quot;set-server-b-as-a-gateway&quot;&gt;Set Server B as a &lt;a href=&quot;/2017/12/29/linux-as-gateway-router/&quot;&gt;Gateway&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;For client A&apos;s visit to remote LAN or even the Internet, server B should be set as a gateway involving the following steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;IP forwarding and &lt;em&gt;optional&lt;/em&gt; Proxy ARP.&lt;/li&gt;
  &lt;li&gt;Iptables FORWARD.&lt;/li&gt;
  &lt;li&gt;Iptables NAT.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;ip-forwarding&quot;&gt;IP Forwarding&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# sysctl -w net.ipv4.ip_forward=1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Usually, IP forwarding is not needed for communication within LAN. However, if peer A want to reach &lt;em&gt;10.0.0.123&lt;/em&gt; without WireGuard setup, it must depend on peer B&apos;s forwarding functionality. This is because A does not have direct Ethernet connection with &lt;em&gt;10.0.0.123&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Needless to say, to reach the Internet through server B, this is a must.&lt;/p&gt;

&lt;h2 id=&quot;proxy-arp-on-server-side&quot;&gt;&lt;a href=&quot;https://www.ericlight.com/wireguard-part-two-vpn-routing.html&quot;&gt;Proxy ARP&lt;/a&gt; on Server Side&lt;/h2&gt;

&lt;p&gt;Optionally, enable Proxy ARP on &lt;em&gt;wg0&lt;/em&gt;. However, it seems this step could be omitted.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Permanent across reboots&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# echo &apos;net.ipv4.conf.wg0.proxy_arp=1&apos; &amp;gt; /etc/sysctl.d/25-proxy_arp.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For the current session:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# sysctl -p /etc/sysctl.d/25-proxy_arp.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# sysctl -w net.ipv4.conf.all.proxy_arp=1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;allow-ip-forwarding-through-iptables&quot;&gt;Allow IP Forwarding through Iptables&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;We assume &lt;em&gt;eth0&lt;/em&gt; is the remote interface that has Internet access.&lt;/li&gt;
  &lt;li&gt;You may also choose to ACCEPT &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i eth0 -o wg0&lt;/code&gt;. For example, server B initiates connection to client A.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;set-up-iptables-nat&quot;&gt;Set up Iptables NAT&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -t nat -A POSTROUTING -i wg0 -o eth0 -s 10.0.0.0/24 -j SNAT --to-source &amp;lt;IP-of-eth0&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Similarly, you may also enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i eth0 -o wg0&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;lan-access&quot;&gt;&lt;a href=&quot;https://www.ericlight.com/wireguard-part-two-vpn-routing.html&quot;&gt;LAN Access&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;In order to reach the whole remote block &quot;10.0.0.0/24* including devices without WireGuard, client A should set &lt;em&gt;allowed-ips&lt;/em&gt; to cover the LAN range.&lt;/p&gt;

&lt;h1 id=&quot;vpn-proxy&quot;&gt;&lt;a href=&quot;https://www.wireguard.com/netns/&quot;&gt;VPN Proxy&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;All client A&apos;s traffic goes through the WireGuard tunnel: to set up VPN routing as a proxy.&lt;/p&gt;

&lt;p&gt;Please be noted that all configurations in this section are done on client A.&lt;/p&gt;

&lt;h2 id=&quot;allowed-ips-catch-all&quot;&gt;&lt;em&gt;allowed-ips&lt;/em&gt; Catch All&lt;/h2&gt;

&lt;p&gt;Similar to LAN Access section above, client A should firstly set its &lt;em&gt;allowed-ips&lt;/em&gt; to cover the catch-all block: &lt;em&gt;0.0.0.0/0&lt;/em&gt; and/or &lt;em&gt;::/0&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;update-client-a-routes&quot;&gt;Update Client A Routes&lt;/h2&gt;

&lt;p&gt;To route all local traffic through the tunnel, the &lt;em&gt;default&lt;/em&gt; route in &lt;em&gt;main&lt;/em&gt; table should be bypassed as it catches all traffic. Specifically, all traffic except that of &lt;em&gt;endpoint&lt;/em&gt; (server B&apos;s public IP) goes to &lt;em&gt;wg0&lt;/em&gt;. The key is to route traffic to &lt;em&gt;wg0&lt;/em&gt; before the &lt;em&gt;default&lt;/em&gt; route entry, such that only traffic to the server is routed through the &lt;em&gt;main&lt;/em&gt; table.&lt;/p&gt;

&lt;p&gt;Of all the methods mentioned below, &lt;em&gt;wg-quick&lt;/em&gt; is robust to peer roaming (endpoint change) as it does not require explicit endpoint routing to be added.&lt;/p&gt;

&lt;h3 id=&quot;replace-the-default-route&quot;&gt;Replace the default Route&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@root ~ &lt;span class=&quot;c&quot;&gt;# ip route del default&lt;/span&gt;
user@root ~ &lt;span class=&quot;c&quot;&gt;# ip route add default dev wg0&lt;/span&gt;
user@root ~ &lt;span class=&quot;c&quot;&gt;# ip route add 23.45.67.89/32 via 192.168.0.1 dev wlan0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;override-the-default-route&quot;&gt;Override the default Route&lt;/h3&gt;

&lt;p&gt;Override the default with two more specific rules that add up to the default but match before the default. We split the default into &lt;em&gt;0.0.0.0/1&lt;/em&gt; and &lt;em&gt;128.0.0.0/1&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@root ~ &lt;span class=&quot;c&quot;&gt;# ip route del default (optional)&lt;/span&gt;
user@root ~ &lt;span class=&quot;c&quot;&gt;# ip route add 0.0.0.0/1 dev wg0&lt;/span&gt;
user@root ~ &lt;span class=&quot;c&quot;&gt;# ip route add 128.0.0.0/1 dev wg0&lt;/span&gt;
user@root ~ &lt;span class=&quot;c&quot;&gt;# ip route add 23.45.67.89/32 via 192.168.0.1 dev wlan0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;rule-based-routing&quot;&gt;Rule-based routing&lt;/h3&gt;

&lt;p&gt;The two methods above operates on route entries of the &lt;em&gt;main&lt;/em&gt; routing table. Here, new routing rules and tables are created.&lt;/p&gt;

&lt;p&gt;Notice: a routing rule is set for a specific routing table, namely to determine which routing table is consulted when routing. Without explicit &lt;em&gt;priority&lt;/em&gt; value, new rules are &lt;em&gt;prepended&lt;/em&gt; to old ones.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Traffic to server&apos;s public IP is routed on the main table.&lt;/span&gt;
user@root ~ &lt;span class=&quot;c&quot;&gt;# ip rule add to 23.45.67.89/32 lookup main pref 30&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# All the rest is routed through WireGuard table.&lt;/span&gt;
user@root ~ &lt;span class=&quot;c&quot;&gt;# ip rule add to all lookup 51820 pref 40&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Create the default route for the new table.&lt;/span&gt;
user@root ~ &lt;span class=&quot;c&quot;&gt;# ip route add default dev wg0 table 51820&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
user@root ~ &lt;span class=&quot;c&quot;&gt;# ip route add 0.0.0.0/0 dev wg0 table 51820&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Routing table 51820 is created for &lt;em&gt;wg0&lt;/em&gt;. A routing table can be referenced by its number or string name.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;pref&lt;/em&gt; means priority of a routing table.&lt;/li&gt;
  &lt;li&gt;The keyword &lt;em&gt;default&lt;/em&gt; can be replaced with &lt;em&gt;0.0.0.0/0&lt;/em&gt; that resembles the catch-all block of &lt;em&gt;allowed-ips&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;wg-quick-method&quot;&gt;&lt;em&gt;wg-quick&lt;/em&gt; method&lt;/h3&gt;

&lt;p&gt;All the three methods above requires explicit route for server&apos;s public IP. However, such configuration is subject to peer roaming where public IP varies without prior notice. &lt;em&gt;wg-quick&lt;/em&gt; utilizes an improved but obscure rule-based method: &lt;em&gt;fwmark&lt;/em&gt; and &lt;em&gt;suppress_prefixlength&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Mark all traffic of *wg0*.
user@root ~ # wg set wg0 fwmark 51820

# Not marked traffic is routed through WireGuard table.
user@root ~ # ip -4 rule add not fwmark 51820 table 51820

# Create the default route for the new table.
user@root ~ # ip -4 route add 0.0.0.0/0 dev wg0 table 51820

# Suppress routing tables that the prefix length of the longest match
# is &amp;lt;= 0 in the main table.
# Namely skip the default entry (prefix length is 0).
user@root ~ # ip -4 rule add table main suppress_prefixlength 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The resulting routing rules look like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0:	from all lookup local 
32764:	from all lookup main suppress_prefixlength 0
32765:	not from all fwmark 0xca6c lookup 51820 
32766:	from all lookup main 
32767:	from all lookup default
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;32764: specific routes in the &lt;em&gt;main&lt;/em&gt; table except the &lt;em&gt;default&lt;/em&gt; is respected.&lt;/li&gt;
  &lt;li&gt;32765: all the rest goes to table 51820.&lt;/li&gt;
  &lt;li&gt;32766: traffic to the server goes to the &lt;em&gt;main&lt;/em&gt; table including the &lt;em&gt;default&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;suppress_prefixlength&quot;&gt;suppress_prefixlength&lt;/h4&gt;

&lt;p&gt;Recall that an IP can be divided into the &lt;em&gt;network part&lt;/em&gt; and the &lt;em&gt;host part&lt;/em&gt;. Prefix length means the length of the network part. For example, the prefix length of &lt;em&gt;192.168.0.100/24&lt;/em&gt; is 24 while that of &lt;em&gt;12.34.56.78/32&lt;/em&gt; is 32.&lt;/p&gt;

&lt;p&gt;Say we have a rule &lt;em&gt;from all lookup table 42 suppress_prefixlength 16&lt;/em&gt;. When network stack hits the rule, it looks up routes in table 42 against destination IP as it would do to rule &lt;em&gt;from all lookup table 42&lt;/em&gt;. When the longest match is found in table 42, it checks the route entry&apos;s prefix length. If the prefix is longer than 16 bits, it proceeds as usual. Otherwise (shorter than or equal to 16 bits), network stack go to check the next routing rule. That is to say, prefix length (of longest match) less than or equal to 16 is ignored (&lt;em&gt;suppressed&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Here is a more detailed explanation. Suppose table 42 contains two entries:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# prefix 8
10.0.0.0/8 dev eth0
# prefix 24
10.1.1.0/24 dev eth1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the destination IP is &lt;em&gt;10.1.1.1&lt;/em&gt;. Obviously, the 2nd entry matches (24 &amp;gt; 16 &amp;gt; 8) and routes the packet to &lt;em&gt;eth1&lt;/em&gt;. If &lt;em&gt;10.2.1.1&lt;/em&gt;, then the 1st entry has the longest match but prefix is less than or equal to 16 bits. Hence table 42 does not route the packet.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;suppress_prefixlength&lt;/code&gt; wants to set a minimal network prefix threshold for routes! The longer a prefix is, the more favored the route entry is: to avoid routes that are too general. Specially, threshold 0 just excludes the &lt;em&gt;default&lt;/em&gt; entry (i.e. &lt;em&gt;default via 192.168.0.1 dev eth0&lt;/em&gt;) as the prefix length is 0 (&lt;em&gt;0.0.0.0/0&lt;/em&gt;). Therefore &lt;em&gt;suppress_prefixlength 0&lt;/em&gt; above suppresses or skips the &lt;em&gt;default&lt;/em&gt; entry in the &lt;em&gt;main&lt;/em&gt; (254) table.&lt;/p&gt;

&lt;h2 id=&quot;procedures-illustrated&quot;&gt;Procedures Illustrated&lt;/h2&gt;

&lt;p&gt;Now let&apos;s go through an example to see how a packet is routed through rules of &lt;em&gt;wg-quick&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;dig @8.8.8.8 www.bing.com&lt;/em&gt; sends DNS query to &lt;em&gt;8.8.8.8&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Network stack hits rule 32764 and checks &lt;em&gt;main&lt;/em&gt; table.&lt;/p&gt;

    &lt;p&gt;The &lt;em&gt;default&lt;/em&gt; entry matches &lt;em&gt;8.8.8.8/32&lt;/em&gt; but its prefix length is 0. So it&apos;s ignored.&lt;/p&gt;

    &lt;p&gt;Suppose there are not any other routes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Network stack checks the next rule 32765.&lt;/p&gt;

    &lt;p&gt;The DNS packet is not marked as 51820 and successfully routed to 51820 table, going to &lt;em&gt;wg0&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;WireGuard received the DNS query packet.&lt;/p&gt;

    &lt;p&gt;It encrypts the packet and forms a new UDP packet with destination IP as &lt;em&gt;endpoint&lt;/em&gt; (server&apos;s public IP). This newly generated packet has &lt;em&gt;fwmark 51820&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Network checks rule 32764 to route the new UDP packet.&lt;/p&gt;

    &lt;p&gt;Similary the &lt;em&gt;default&lt;/em&gt; entry is ignored.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Network stack checks rule 32765.&lt;/p&gt;

    &lt;p&gt;Due to &lt;em&gt;fwmark 51820&lt;/em&gt;, table &lt;em&gt;51820&lt;/em&gt; is ignored either.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Network stack checks rule 32766.&lt;/p&gt;

    &lt;p&gt;It&apos;s the &lt;em&gt;main&lt;/em&gt; table again. This time there is no &lt;em&gt;suppress_prefixlength 0&lt;/em&gt; limit. The WireGuard UDP packet is routed to &lt;em&gt;default&lt;/em&gt; entry of &lt;em&gt;main&lt;/em&gt; table, going out!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;policy-routing-based-on-bare-ips&quot;&gt;Policy Routing Based on Bare IPs&lt;/h1&gt;

&lt;p&gt;In VPN Proxy section, traffic with &lt;em&gt;fwmark&lt;/em&gt; is routed through the &lt;em&gt;main&lt;/em&gt; table while that without the mark is routed through &lt;em&gt;wg0&lt;/em&gt; table. Therefore, all traffic by default goes through WireGuard. Such all-in-one routing method is somewhat inefficient.&lt;/p&gt;

&lt;p&gt;For example, we can route some traffic (i.e. to &lt;em&gt;www.baidu.com&lt;/em&gt;) through the main table while some (i.e. to &lt;em&gt;www.block.com&lt;/em&gt;) through &lt;em&gt;wg0&lt;/em&gt; table. To achieve smart routing, we can mark former part while leaving the rest alone.&lt;/p&gt;

&lt;p&gt;To set &lt;em&gt;fwmark&lt;/em&gt; for a packet, we can resort to Iptables and IP set with the help of &lt;em&gt;dnsmasq&lt;/em&gt; like &lt;a href=&quot;/2018/03/26/policy-routing/&quot;&gt;this post&lt;/a&gt;. Obviously, there is no need to modify the routing rules and tables above.&lt;/p&gt;

&lt;p&gt;The two methods followed are somewhat less elegant but deserves attention. They are mainly based on bare IPs.&lt;/p&gt;

&lt;h2 id=&quot;ip-set&quot;&gt;IP set&lt;/h2&gt;

&lt;p&gt;Firstly, we divide IPs into two sets. Traffic of one goes to WireGuard while the other not. IPs are from &lt;a href=&quot;http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest&quot;&gt;APNIC Delegated List&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;CN set:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# wget -O- &apos;http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest&apos; | awk -F\| &apos;/CN\|ipv4/ { printf(&quot;%s/%d\n&quot;, $4, 32-log($5)/log(2)) }&apos; &amp;gt; CNip.txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;non-CN set:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# wget -O- &apos;http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest&apos; | awk -F\| &apos;/\|ipv4\|/ &amp;amp;&amp;amp; ! /\|CN\|/ &amp;amp;&amp;amp; ! /\|\*\|/ { printf(&quot;%s/%d\n&quot;, $4, 32-log($5)/log(2)) }&apos; &amp;gt; nonCNip.txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can set a &lt;em&gt;cron&lt;/em&gt; job to update IP set.&lt;/p&gt;

&lt;h3 id=&quot;static-route-method&quot;&gt;Static Route Method&lt;/h3&gt;

&lt;p&gt;One obvious method is adding all IPs of non-CN set to server peer&apos;s &lt;em&gt;allowed-ips&lt;/em&gt; while removing the catch-all &lt;em&gt;0.0.0.0/0&lt;/em&gt;. &lt;em&gt;wg-quick&lt;/em&gt; will create the relevant routes in &lt;em&gt;main&lt;/em&gt; table like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1.0.128.0/17 dev wg0 proto kernel scope link src 10.0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, that would fluff the &lt;em&gt;allowed-ips&lt;/em&gt; list and increase maintainance burden.&lt;/p&gt;

&lt;p&gt;Similarly we can also create routes in &lt;em&gt;main&lt;/em&gt; table for IPs of CN set like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1.0.32.0/19 via 192.168.0.1 dev wlan0 proto dhcp src 192.168.0.123 metric 304
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I will choose the 2nd method as:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# xargs -a /etc/wireguard/CNip.txt -I&apos;{}&apos; ip route add &apos;{}&apos; via 192.168.0.1 dev wlan0 proto dhcp src 192.168.0.123 metric 304&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# wget -O- &apos;http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest&apos; | awk -F\| &apos;/CN\|ipv4/ { printf(&quot;%s/%d\n&quot;, $4, 32-log($5)/log(2)) }&apos; | xargs -I&apos;{}&apos; ip route add &apos;{}&apos; via 192.168.0.1 dev wlan0 proto dhcp src 192.168.0.123 metric 304&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Don&apos;t worry about route entries if you manually bring down WireGuard.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We have &lt;em&gt;src&lt;/em&gt; in the route entries, which would fail if &lt;em&gt;wlan0&lt;/em&gt; or &lt;em&gt;wg0&lt;/em&gt; do not have a IP the time we add routes (i.e. Wi-Fi router down).&lt;/p&gt;

    &lt;p&gt;To simplify things, just remove &lt;em&gt;src&lt;/em&gt; part. If you&apos;d like, remove &lt;em&gt;metric&lt;/em&gt; and &lt;em&gt;proto&lt;/em&gt; as well.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Read more on &lt;a href=&quot;https://github.com/fivesheep/chnroutes&quot;&gt;chnroutes&lt;/a&gt; and &lt;a href=&quot;https://gist.github.com/lixingcong/286144b3a521add58d8dcf045700963f&quot;&gt;chinaroute路由表更新命令&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;geoip-method&quot;&gt;Geoip method&lt;/h3&gt;

&lt;p&gt;Instead of IP set, we can make use of &lt;em&gt;geopip&lt;/em&gt; extension of &lt;em&gt;iptables&lt;/em&gt;. This is much more simpler.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ # iptables -t mangle -A OUTPUT -o wlan0 -m geoip --dst-cc CN -j MARK --set-mark 51820
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Recall the &lt;em&gt;ip rule&lt;/em&gt; above, packets with &lt;em&gt;51820&lt;/em&gt; mark will be routed by &lt;em&gt;main&lt;/em&gt; table as usual.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://worldend.logdown.com/posts/304263-gentoo-install-iptables-geoip&quot;&gt;Gentoo Geoip&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/woods/25ef91a95da85bf10974&quot;&gt;woods/geoip.sh&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://daenney.github.io/2017/01/07/geoip-filtering-iptables.html&quot;&gt;GeoIP based filtering with iptables&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;improve-local-dns-servers&quot;&gt;Improve Local DNS Servers&lt;/h2&gt;

&lt;p&gt;Policy routing based on IPs highly depends on correct DNS resolving when visiting a domain. Accordingly, a custom clean DNS server (i.e. &lt;em&gt;8.8.8.8&lt;/em&gt;) other than the one provided by ISP (prone to DNS poisoning) is required. This, in turn, would degrade performance when visiting domestic domains as custom DNS servers such as &lt;em&gt;8.8.8.8&lt;/em&gt; usually return IPs geographically far.&lt;/p&gt;

&lt;p&gt;Consequentially, smart DNS service that resolves domestic domains as usual (geographically nearby) but censorshipped domains correctly. There exist such smart DNS servers around. Just make sure traffic to it goes to WireGuard! In other words, organize IPs of smart DNS servers into the non-CN set. The goal is to set system DNS servers such that they resolve domestic domains into IPs of CN set while foreign domains into IPs of non-CN set.&lt;/p&gt;

&lt;p&gt;Alternatively, a smart DNS server can be set locally such like &lt;a href=&quot;https://github.com/shadowsocks/ChinaDNS&quot;&gt;ChinaDNS&lt;/a&gt;. An far better method is illustrated in &lt;a href=&quot;/2018/03/26/policy-routing/&quot;&gt;iproute2, iptables, dnsmasq&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;wg-quick&quot;&gt;wg-quick&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;wg-quick&lt;/em&gt; is just a wrapper script of commands of &lt;em&gt;ip&lt;/em&gt; and &lt;em&gt;wg&lt;/em&gt; above to faciliate the interface and WireGuard setup.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# wg-quick [ up | down | save ] [ CONFIG_FILE | INTERFACE ]&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# wg-quick save wg0&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# wg-quick up wg0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please make sure &lt;em&gt;/etc/wireguard/INTERFACE.conf&lt;/em&gt; file exist.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Attention&lt;/em&gt;: the configuration file of &lt;em&gt;wg-quick&lt;/em&gt; introduces a few extra arguments (i.e. internal IP, DNS) to format understood by &lt;em&gt;wg&lt;/em&gt; in order to configure additional attributes. &lt;em&gt;wg-quick&lt;/em&gt; handles the values that it understands, and then passes the rest directly to &lt;em&gt;wg setconf&lt;/em&gt;. Especially, &lt;em&gt;wg-quick&lt;/em&gt; update system route table automatically.&lt;/p&gt;

&lt;p&gt;Here is an client example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Interface]
ListenPort = 48574
Address = 10.0.0.1/24
DNS = 8.8.8.8
SaveConfig = true
PrivateKey = EOpLmUJ08uwH2z2NpBwJ2upWzB5Tn36nhQvlXccAFnk

[Peer]
PublicKey = 7nXZYaqyXuVdW0RwHauMJuW81axAM9hSavY9JIJsZFU=
AllowedIPs = 10.0.0.2/32
Endpoint = 23.45.67.89:39814
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see that &quot;Address&quot;, &quot;DNS&quot; and &quot;SaveConfig&quot; items are added. The DNS defined by &lt;em&gt;wg-quick&lt;/em&gt; will replace local ones with help of &lt;em&gt;resolvconf&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here is an server example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Interface]
Address = 10.0.0.2/24
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 39814
PrivateKey = [SERVER PRIVATE KEY]

[Peer]
PublicKey = [CLIENT PUBLIC KEY]
AllowedIPs = 10.0.0.1/32  # Client&apos;s internal IP.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;booting&quot;&gt;Booting&lt;/h1&gt;

&lt;h2 id=&quot;gentoo-wg-quick&quot;&gt;Gentoo wg-quick&lt;/h2&gt;

&lt;p&gt;Here I use &lt;em&gt;local.d&lt;/em&gt; startup script. Please make sure the scripts are executable.&lt;/p&gt;

&lt;p&gt;Up: &lt;em&gt;/etc/local.d/01-wireguard.start&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Starting WireGuard ...&quot;&lt;/span&gt;
/usr/bin/wg-quick up wg0

&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Adding CNip routes in background ...&quot;&lt;/span&gt;
xargs &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; /etc/wireguard/CNip.txt &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; ip route add &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; via 192.168.0.1 dev wlan0 proto dhcp src 192.168.0.123 metric 304 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The route part can be moved to &lt;em&gt;/etc/dhcpcd.exit-hook&lt;/em&gt; as well. But on my system, &lt;em&gt;dhcpcd&lt;/em&gt; reports:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Error: Device for nexthop is not up&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From the message, &lt;em&gt;wlan0&lt;/em&gt; is not up before route entries added.&lt;/p&gt;

&lt;p&gt;Down: &lt;em&gt;/etc/local.d/01-wireguard.stop&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Stopping WireGuard ...&quot;&lt;/span&gt;
/usr/bin/wg-quick down wg0

&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Removing CNip routes in background ...&quot;&lt;/span&gt;
xargs &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; /etc/wireguard/CNip.txt &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; ip route del &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; via 192.168.0.1 dev wlan0 proto dhcp src 192.168.0.123 metric 304 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, the &lt;em&gt;local&lt;/em&gt; service will silence all output. Setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc_verbose=yes&lt;/code&gt; will cause it to show which scripts were run and their output, if any.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/conf.d/local
rc_verbose=yes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc_verbose&lt;/code&gt; in &lt;em&gt;/etc/rc.conf&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;systemd-wg-quick&quot;&gt;systemd wg-quick&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# systemctl enable wg-quick@wg0&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# systemctl start wg-quick@wg0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;cron-job&quot;&gt;cron job&lt;/h2&gt;

&lt;p&gt;Set a cron job to update IP set daily.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# crontab -u root -e&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
9  14  &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;     root    wget &lt;span class=&quot;nt&quot;&gt;-O-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest&apos;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\|&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/CN\|ipv4/ { printf(&quot;%s/%d\n&quot;, $4, 32-log($5)/log(2)) }&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/wireguard/CNip.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, we can set a script file (executable) into &lt;em&gt;/etc/cron.daily/&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#/etc/cron.daily/CNip&lt;/span&gt;

wget &lt;span class=&quot;nt&quot;&gt;-O-&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest&apos;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\|&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/CN\|ipv4/ { printf(&quot;%s/%d\n&quot;, $4, 32-log($5)/log(2)) }&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/wireguard/CNip.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;notes&quot;&gt;Notes&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;wg-quick up&lt;/em&gt; process:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[#] ip link add wg-quick type wireguard
[#] wg setconf wg-quick /dev/fd/63
[#] ip address add 192.168.57.1/24 dev wg-quick
[#] ip link set mtu 1420 dev wg-quick
[#] ip link set wg-quick up
[#] resolvconf -a wg-quick -m 0 -x
[#] wg set wg-quick fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg-quick table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;wg-quick down&lt;/em&gt; process:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[#] wg showconf wg-quick
[#] ip -4 rule delete table main suppress_prefixlength 0
RTNETLINK answers: Address family not supported by protocol
Dump terminated
RTNETLINK answers: Address family not supported by protocol
Dump terminated
[#] ip link delete dev wg-quick
[#] resolvconf -d wg-quick
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ericlight.com/wireguard-part-two-vpn-routing.html&quot;&gt;Wireguard - Part Two (VPN routing)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.lilydjwg.me/2017/10/10/wireguard.210886.html&quot;&gt;WireGuard: 简单好用的 VPN&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://lwn.net/Articles/748582/&quot;&gt;Virtual private networks with WireGuard&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.wireguard.com/quickstart/&quot;&gt;Quick Start&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/&quot;&gt;wireguard-vpn-typical-setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://staaldraad.github.io/2017/04/17/nat-to-nat-with-wireguard/&quot;&gt;NAT-to-NAT VPN with WireGuard&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nbsoftsolutions.com/blog/wireguard-vpn-walkthrough&quot;&gt;WireGuard VPN Walkthrough&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>VPN versus proxy</title>
   <link href="/2018/03/19/vpn-vs-proxy/"/>
   <updated>2018-03-19T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/03/19/vpn-vs-proxy</id>
   <content type="html">&lt;p&gt;VPN and proxy both can, more or less, serve as a man in the middle to target network. VPN is meant to establish private (encryption) connection to target network over the Internet. Proxy is just a traffic relay though developers may decide to implement security enhancement. Therefore, VPN can be an alternative to proxy for security concern.&lt;/p&gt;

&lt;p&gt;Here is a simple flow illustration:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;VPN: application - VPN client (encrypt traffic) - the Internet - VPN server (decrypt traffic) on target network&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Proxy: application - proxy client (opt) - proxy server - target network&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;VPN as proxy: application - VPN client (encrypt traffic) - the Internet - VPN server (decrypt traffic) - target network&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;proxy&quot;&gt;Proxy&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;With proxy, traffic appears to come from somewhere else hiding your IP from target network.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;HTTP proxy is only designed for web traffic while SOCKS proxy is indifferent to the type of traffic (HTTP, FTP, BT etc.) that passes through it.&lt;/p&gt;

    &lt;p&gt;SOCKS is slower than HTTP as it require more overhead.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;HTTP proxying has a different usage model in mind, the CONNECT method allows for forwarding TCP connections like SOCKS proxy.&lt;/p&gt;

    &lt;p&gt;HTTPS proxy requires the CONNECT method.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;SOCKS works on TCP mostly. But SOCKS5 provides a means for UDP packets to be forwarded.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;security&quot;&gt;Security&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;As mentioned above, proxy by nature, does not protect traffic security.&lt;/li&gt;
  &lt;li&gt;BT over proxy would reveal your IP. Try BTGuard instead.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;vpn&quot;&gt;VPN&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;VPN encrypt connection to provide private communication by design.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;VPN creats a virtual interface at the operating system level, and the VPN connection captures the entire network connection of the device it is configured on.&lt;/p&gt;

    &lt;p&gt;Proxy, on the other hand, needs enabled on application basis.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Encryption and decryption incur much more overhead than SOCKS proxy, let alone HTTP proxy.&lt;/li&gt;
  &lt;li&gt;UDP VPN (i.e. WireGuard) is faster than TCP VPN (OpenVPN) but less reliable.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Eng</title>
   <link href="/2018/03/07/eng/"/>
   <updated>2018-03-07T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/03/07/eng</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;for ease of review, this post is moved to cloud.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;A report from Gizmodo says that Google is &lt;em&gt;partnering with&lt;/em&gt; the United States Department of Defense and building drone software.&lt;/p&gt;

    &lt;p&gt;partner with&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We had to admire his prowess as an oarsman/his rowing &lt;em&gt;prowess&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;prowess: Someone&apos;s prowess is their great skill at doing something. (FORMAL)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;A &lt;em&gt;pilot&lt;/em&gt; scheme or a pilot project is one which is used to test an idea before deciding whether to introduce it on a larger scale.&lt;/li&gt;
  &lt;li&gt;If one group of people &lt;em&gt;leapfrog&lt;/em&gt;s into a particular position or leapfrogs someone else, they use the achievements of another person or group in order to make advances of their own.&lt;/li&gt;
  &lt;li&gt;A &lt;em&gt;patio&lt;/em&gt; is an area of flat blocks or concrete next to a house, where people can sit and relax or eat.&lt;/li&gt;
  &lt;li&gt;A &lt;em&gt;bartender&lt;/em&gt; is a person who serves drinks behind a bar. (AM; in BRIT, use barman, barmaid)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;ox/beef; pig/pork; lamb/sheep/mutton.&lt;/p&gt;

    &lt;p&gt;If you &lt;em&gt;beef up&lt;/em&gt; something, you increase, strengthen, or improve it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The oldest type of proxy server, HTTP proxies are designed &lt;em&gt;expressly&lt;/em&gt; for web-based traffic.&lt;/p&gt;

    &lt;p&gt;An &lt;em&gt;express&lt;/em&gt; command or order is one that is clearly and deliberately stated.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you &lt;em&gt;eavesdrop&lt;/em&gt; on someone, you listen secretly to what they are saying.&lt;/p&gt;

    &lt;p&gt;eavesdropper.&lt;/p&gt;

    &lt;p&gt;The government illegally eavesdropped on his telephone conversations…&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A &lt;em&gt;toll&lt;/em&gt; is a total number of deaths, accidents, or disasters that occur in a particular period of time. (JOURNALISM)&lt;/p&gt;

    &lt;p&gt;There are fears that the casualty toll may be higher.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are a variety options to do this, and if you&apos;re a &lt;em&gt;seasoned&lt;/em&gt; sysadmin you probably already have a favourite way.&lt;/p&gt;

    &lt;p&gt;You can use &lt;em&gt;seasoned&lt;/em&gt; to describe a person who has a lot of experience of something. For example, a seasoned traveller is a person who has travelled a lot.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A &lt;em&gt;reciprocal&lt;/em&gt; action or agreement involves two people or groups who do the same thing to each other or agree to help each another in a similar way. (FORMAL)&lt;/p&gt;

    &lt;p&gt;They expected a &lt;em&gt;reciprocal&lt;/em&gt; gesture before more hostages could be freed…&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Something, especially food, that is &lt;em&gt;kosher&lt;/em&gt; is approved of or allowed by the laws of Judaism.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Someone who &lt;em&gt;is agile&lt;/em&gt; can move quickly and easily. If you have &lt;em&gt;an agile mind&lt;/em&gt;, you think quickly and intelligently.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In finance, a &lt;em&gt;portfolio&lt;/em&gt; is the combination of shares or other investments that a particular person or company has.&lt;/p&gt;

    &lt;p&gt;A case for carrying papers or drawings or maps; usually leather.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;It &lt;em&gt;is more than&lt;/em&gt; a piece of technology and orchestration.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;em&gt;topography&lt;/em&gt; of a particular area is its physical shape, including its hills, valleys, and rivers.&lt;/p&gt;

    &lt;p&gt;The &lt;em&gt;geography&lt;/em&gt; of a place is the way that features such as rivers, mountains, towns, or streets are arranged within it.&lt;/p&gt;

    &lt;p&gt;It is important to remember that &lt;em&gt;topographically&lt;/em&gt; closer does not inherently mean &lt;em&gt;geographically&lt;/em&gt; closer, though this is often the case.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;penultimate&lt;/em&gt; thing in a series of things is &lt;em&gt;the last but one&lt;/em&gt;. (FORMAL)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If someone or something &lt;em&gt;aggravate&lt;/em&gt;s a situation, they make it worse.&lt;/p&gt;

    &lt;p&gt;If someone or something &lt;em&gt;aggravate&lt;/em&gt;s you, they make you annoyed. (INFORMAL)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;mileage&lt;/em&gt; in a particular course of action is its usefulness in getting you what you want.&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;[find | consider | see] [it | him] [to be | [as] being] [ very | rather] [appropriate | amusing | strange&lt;/td&gt;
          &lt;td&gt;inappropriate]&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;&lt;em&gt;to be&lt;/em&gt; and &lt;em&gt;being&lt;/em&gt; means different context.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;reverse course; impose tariffs on; in response to; rescind sanctions against;&lt;/li&gt;
  &lt;li&gt;If a government or a group of people in power &lt;em&gt;rescind&lt;/em&gt; a law or agreement, they officially withdraw it and state that it is no longer valid. (FORMAL)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;A slew of&lt;/em&gt; things is a large number of them. (mainly AM)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you &lt;em&gt;wield&lt;/em&gt; a weapon, tool, or piece of equipment, you carry and use it.&lt;/p&gt;

    &lt;p&gt;If someone &lt;em&gt;wield&lt;/em&gt;s power, they have it and are able to use it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;If a group of people or things &lt;em&gt;fan out&lt;/em&gt;, they move forwards away from a particular point in different directions.&lt;/li&gt;
  &lt;li&gt;Some concerns have been raised that …&lt;/li&gt;
  &lt;li&gt;ledger, tally, bookkeeping/bookkeeper&lt;/li&gt;
  &lt;li&gt;to = (in order) to = (so as) to = so that;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If a boyfriend or girlfriend &lt;em&gt;stands you up&lt;/em&gt;, they fail to keep an arrangement to meet you. (INFORMAL)&lt;/p&gt;

    &lt;p&gt;stand sb up; no show no call;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A &lt;em&gt;contingency&lt;/em&gt; is something that might happen in the future (= possibility, eventuality).&lt;/p&gt;

    &lt;p&gt;A &lt;em&gt;contingency measure/plan&lt;/em&gt; is one that is intended to be used if a possible situation actually occurs.&lt;/p&gt;

    &lt;p&gt;in case of contingency&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Windows</title>
   <link href="/2018/01/01/windows/"/>
   <updated>2018-01-01T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2018/01/01/windows</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#prevent-win10-1803-auto-restart&quot; id=&quot;markdown-toc-prevent-win10-1803-auto-restart&quot;&gt;Prevent Win10 1803 auto-restart&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#security&quot; id=&quot;markdown-toc-security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#drivers&quot; id=&quot;markdown-toc-drivers&quot;&gt;Drivers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#windows-embedded-standard-7&quot; id=&quot;markdown-toc-windows-embedded-standard-7&quot;&gt;Windows Embedded Standard 7&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#add-more-features&quot; id=&quot;markdown-toc-add-more-features&quot;&gt;Add more features&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#activation&quot; id=&quot;markdown-toc-activation&quot;&gt;Activation&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#mak&quot; id=&quot;markdown-toc-mak&quot;&gt;MAK&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#key-management-server-kms&quot; id=&quot;markdown-toc-key-management-server-kms&quot;&gt;Key Management Server (KMS)&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#kms-emulator&quot; id=&quot;markdown-toc-kms-emulator&quot;&gt;KMS emulator&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#gvlk&quot; id=&quot;markdown-toc-gvlk&quot;&gt;GVLK&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#configure-a-client&quot; id=&quot;markdown-toc-configure-a-client&quot;&gt;Configure a client&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#activate-a-product&quot; id=&quot;markdown-toc-activate-a-product&quot;&gt;Activate a product&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#references&quot; id=&quot;markdown-toc-references&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;prevent-win10-1803-auto-restart&quot;&gt;Prevent Win10 1803 auto-restart&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Run &lt;em&gt;gpedit.msc&lt;/em&gt; as administrator;&lt;/li&gt;
  &lt;li&gt;Computer Configuration - Administration Template - Windows Update&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Configure Automatic Updates - Enabled&lt;/p&gt;

    &lt;p&gt;Choose &apos;4 - Auto download and schedule the install&apos;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;No auto-restart with logged on users for shceduled automatic updates installations - Enabled&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;security&quot;&gt;Security&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://blogs.technet.microsoft.com/msrc/2017/05/12/customer-guidance-for-wannacrypt-attacks/&quot;&gt;WannaCry / Wcry / WannaCrypt&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;https://support.microsoft.com/en-us/help/2696547/how-to-detect-enable-and-disable-smbv1-smbv2-and-smbv3-in-windows-and&quot;&gt;Turn off&lt;/a&gt; SMB v1 and optionally v2 and/or v3. Then check by:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;netstat -na | find &quot;LISTENING&quot; | find &quot;:445 &quot;&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Especially, &lt;a href=&quot;https://superuser.com/q/1208963&quot;&gt;Windows XP SP3&lt;/a&gt; requires patch &lt;a href=&quot;https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=55245&quot;&gt;Windows XP SP3 安全更新程序 (KB4012598)&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Anything related to Intel Management Engine (IME)  or Automatic Management Technology (AMT) should be avoid.&lt;/li&gt;
  &lt;li&gt;Turn off Windows Defender (scan disk) with &lt;em&gt;gpedit.msc&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;drivers&quot;&gt;Drivers&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Unlike Widnows 8 onwards, Windows 7 ISO lack drivers (i.e. Ethernet, Wireless etc.). Upon installation, it probably cannot connect the Internet.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;windows-embedded-standard-7&quot;&gt;Windows Embedded Standard 7&lt;/h1&gt;

&lt;p&gt;Installation tips:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use a Template - Thin Client.&lt;/li&gt;
  &lt;li&gt;Modify Drivers &amp;amp; Modify Features.&lt;/li&gt;
  &lt;li&gt;Automatically detect devices.&lt;/li&gt;
  &lt;li&gt;Untick &apos;Resolve optional dependencies&apos; otherwise final OS Footprint would be 3.4G around. Leave &apos;Resolve Dependencies&apos; to the last step of package selection, which otherwise would pulls uncessary leftover.&lt;/li&gt;
  &lt;li&gt;.Net Framework, tick everything. Miscellaneous applications depend on .NET framework.&lt;/li&gt;
  &lt;li&gt;Application Support, untick &apos;MSMQ&apos;.&lt;/li&gt;
  &lt;li&gt;Boot Environments, &apos;Enhanced write filter boot Environment&apos; to &apos;Windows Boot Environment&apos;.&lt;/li&gt;
  &lt;li&gt;Browsers, keep IE 8.&lt;/li&gt;
  &lt;li&gt;Data Access and Storage, untick &apos;Windows Data Access Components - SQL&apos;.&lt;/li&gt;
  &lt;li&gt;Data Integrity, leave everything unticked.&lt;/li&gt;
  &lt;li&gt;Devices and Printers, untick &apos;Printing Utilities and Management&apos;.&lt;/li&gt;
  &lt;li&gt;Diagnostics, leave &apos;Common Diagnostics Tools&apos; and optionally &apos;User&apos; ticked (Windows Task Manager).&lt;/li&gt;
  &lt;li&gt;Embedded Enabling Features, untick everything and optionally tick &apos;Registry Filter&apos; (for &lt;em&gt;regedit&lt;/em&gt;).&lt;/li&gt;
  &lt;li&gt;Fonts, tick &apos;Simplified Chinese Fonts&apos;.&lt;/li&gt;
  &lt;li&gt;Graphics and Multimedia, untick &apos;Windows Media Player 12&apos;.&lt;/li&gt;
  &lt;li&gt;International, leave everything unticked.&lt;/li&gt;
  &lt;li&gt;Internet Information Service - IIS, leave everything unticked.&lt;/li&gt;
  &lt;li&gt;Management, leave it alone but optionally untick &apos;Windows Update User Interface&apos;.&lt;/li&gt;
  &lt;li&gt;MediaCenter, leave everything unticked.&lt;/li&gt;
  &lt;li&gt;Networking, untick everything and tick &apos;Network and Sharing Center&apos;, and optionally &apos;Wireless Networking&apos;. With regards to &apos;Wireless Networking&apos; part, VirtualBox does &lt;strong&gt;not&lt;/strong&gt; support wirless adapters (only simulates Ethernet), which means you cannot add or see wirless adapter in Windows Device Manager. However, you can attach a USB Wi-Fi stick to guest OS and connect directly to Wi-Fi router.&lt;/li&gt;
  &lt;li&gt;Remote Connections, untick &apos;Remote Desktop Connection&apos;.&lt;/li&gt;
  &lt;li&gt;Security, untick everything.&lt;/li&gt;
  &lt;li&gt;System Services, leave it alone.&lt;/li&gt;
  &lt;li&gt;User Interface, untick &apos;Help&apos;, &apos;Microsoft Speech API&apos;, and &apos;Accessibility&apos;.&lt;/li&gt;
  &lt;li&gt;Resolve Dependencies. Choose &apos;Unbranded Startup Screens&apos;, &apos;Windows Boot Environment&apos;, &apos;Standard Windows USB Stack&apos; and &apos;Windows Explorer Shell&apos; (a MSUT). Some previously unticked feature might be ticked again as a dependency of some other features.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;add-more-features&quot;&gt;Add more features&lt;/h2&gt;

&lt;p&gt;Suppose you have unticked an feature (i.e. IE 8), and want to add it back after installation, do the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Find the feature package &lt;em&gt;cabinet&lt;/em&gt; file from ISO, like &lt;em&gt;DS/Packages/FeaturePack/x86~winemb-ie-explorer~~~~6.1.7600.16385~1.0/WinEmb-IE-Explorer.cab&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Use &lt;em&gt;Pkgmr&lt;/em&gt; or &lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/dism-operating-system-package-servicing-command-line-options&quot;&gt;DISM&lt;/a&gt; command line to install the cabinet file. &lt;em&gt;dism&lt;/em&gt; is far more powerful than what you think. For example, you can use it to check a cabinet file information.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Do it in an elevated command prompt.
DISM /?
Pkgmgr /?
DISM /Online /Add-Package /PackagePath:&quot;C:\Users\Brink\Desktop\WinEmb-IE-Explorer.cab&quot;
Pkgmgr /ip /m:C:\Users\Brink\Desktop\WinEmb-IE-Explorer.cab
# restart system as requested
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;activation&quot;&gt;Activation&lt;/h1&gt;

&lt;h2 id=&quot;mak&quot;&gt;MAK&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Windows XP Professional VOL SP3 x86&lt;/p&gt;

    &lt;p&gt;MRX3F-47B9T-2487J-KWKMF-RPWBY&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Windows Emebedded 7 Standard x86&lt;/p&gt;

    &lt;p&gt;XGY72-BRBBT-FF8MH-2GG8H-W7KCW MPMVY-PP762-WWVBC-83RXJ-2H7RH GJVTR-C4WQ6-BKRH3-DRFFH-J83DM&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;key-management-server-kms&quot;&gt;Key Management Server (KMS)&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;KMS activation is not permanent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A Microsoft Key Management Server (KMS) is a legitimate service offered under Microsoft Volume Activation 2.0 solution which is used to activate &lt;em&gt;volume&lt;/em&gt; licensed Microsoft products. It works with minimal administration intervention and allows automated activation of Microsoft products (i.e. Windows OS, Office, Visio etc.).&lt;/p&gt;

&lt;p&gt;With KMS activation method, the client (Microsft products) contacts verification server periodically to renew license. Each activation holds the license for 180 days. I will not go into details on KMS mechanism.&lt;/p&gt;

&lt;p&gt;Here, I will set up a self-hosted KMS server :) based on FOSS reverse engineering code. Before that, please review a few notes on KMS:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;KMS activates only Volume (VOL) licensing Microsoft products.&lt;/p&gt;

    &lt;p&gt;&apos;Windows Enterprise&apos; is certainly VOL licensed while &apos;Windows Professionl&apos; use either VOL license or retail license. Office versions downloaded from Microsoft MSDN and/or Technet are non-VOL. It&apos;s recommended to download VOL licensing editions from &lt;a href=&quot;https://msdn.itellyou.cn&quot;&gt;itellyou.cn&lt;/a&gt;.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;MAK activation method (one key forever) makes life easier on the premise that you succeed in finding a MAK key.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Where to put the KMS server side?&lt;/p&gt;

    &lt;p&gt;Intuitively, we can deploy it on Windows system to be activated. However, local server may be compromised by Windows updates or anti-virus software. Beginning with Windows 8.1 the KMS server must be a different computer than the client. You cannot use &lt;em&gt;vlmcsd&lt;/em&gt; on the same computer where you want to activate a product. If you have only one computer, you can run vlmcsd in a virtual machine. It&apos;s better to put the server side on a alway-on devices like VPS.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;kms-emulator&quot;&gt;&lt;a href=&quot;https://www.efe.cc/?post=239&quot;&gt;KMS emulator&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Among the other things, &lt;a href=&quot;https://github.com/Wind4/vlmcsd&quot;&gt;vlmcsd in C&lt;/a&gt; and &lt;a href=&quot;https://github.com/ThunderEX/py-kms/&quot;&gt;py-kms in Python2&lt;/a&gt; are the most popular KMS emulators. They can run on almost any platforms like Windows, Cygwin, Linux, Android, OpenWrt, Unix, BSD etc. Here, I choose &lt;em&gt;vlmcsd&lt;/em&gt; on CentOS 7 as an example.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;To set up KMS emulator on Windows system, you&apos;d better use &lt;em&gt;py-kms&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Firstly, build binaries from source.&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-bash\&quot;&gt;root@tux / # cd /opt/
root@tux opt # git clone --depth=1 https://github.com/Wind4/vlmcsd.git
root@tux opt # cd vlmcsd
root@tux opt # man man/vlmcsd.7
root@tux opt # make
root@tux opt # chown -R nobody: /opt/vlmcsd
root@tux opt # cd bin
root@tux opt # vlmcsd -h
root@tux opt # vlmcs -h
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;The author also provides pre-compiled binaries on Github relase page.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Launch KMS server&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# /opt/vlmcsd/bin/vlmcsd -g nobody -u nobody -o3 -m1 -t15 -d -lsyslog -Dev&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# /opt/vlmcsd/bin/vlmcsd -i /opt/vlmcsd/etc/vlmcsd.ini&lt;/span&gt;
   
root@tux / &lt;span class=&quot;c&quot;&gt;# journalctl -xeft vlmcsd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The options &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-D&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e&lt;/code&gt; are useful for terminal debugging.&lt;/p&gt;

    &lt;p&gt;We can load configuration file by the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i&lt;/code&gt; and run &lt;em&gt;vlmcsd&lt;/em&gt; in background, such that we can send the &quot;HUP&quot; signal to &lt;em&gt;vlmcsd&lt;/em&gt; process without restarting.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# man man/vlmcsd.ini.5

User = nobody
Group = nobody
PublicIPProtectionLevel = 3
MaxWorkers = 1
ConnectionTimeout = 15
DisconnectClientsImmediately = TRUE
LogFile = syslog
LogVerbose = TRUE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Command line options take precedence over the respective configuration line in the &lt;em&gt;.ini&lt;/em&gt; file. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-k&lt;/code&gt; (do not disconnect clients) on command line overrides &apos;DisconnectClientsImmediately = TRUE&apos;.&lt;/p&gt;

    &lt;p&gt;About configuration options, please check &lt;em&gt;etc/vlmcsd.ini&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Firewalld&lt;/p&gt;

    &lt;p&gt;Make sure the relevant port are accessible from outside.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Test KMS server locally&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# journalctl -xeft vlmcsd&lt;/span&gt;

user@tux ~ &lt;span class=&quot;c&quot;&gt;# /opt/vlmcsd/bin/vlmcs 127.0.0.1:1688 -v -e  # print examples&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# /opt/vlmcsd/bin/vlmcs -v -x        # print supported Windows and Office versions&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# /opt/vlmcsd/bin/vlmcs -v -l 35     # activate Windows 7 Enterprise&lt;/span&gt;
   
user@tux ~ &lt;span class=&quot;c&quot;&gt;# /opt/vlmcsd/bin/vlmcs vlmcsd.example.com:1234 -v -l 35     # check if firewall allows public access&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;vlmcs&lt;/em&gt; tests against a KMS server that can be a &lt;em&gt;vlmcsd&lt;/em&gt; emulator or a real Microsoft KMS.&lt;/li&gt;
      &lt;li&gt;A Microsoft KMS sends correct activation messages only if it detects a certain minimum of clients (25 for Windows client OSses, 5 otherwise) on the network. This is Microsoft&apos;s futile attempt to prevent running a KMS server in a home environment. Use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n&lt;/code&gt; argument to charges a KMS server. The &lt;em&gt;vlmcsd&lt;/em&gt; emulator is always fully charged, so I set MaxWorkers to 1. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n&lt;/code&gt; is larger than 1, &lt;em&gt;vlmcsd&lt;/em&gt; will report RPC error.&lt;/li&gt;
      &lt;li&gt;The above &lt;em&gt;vlmcs&lt;/em&gt; client runs in the same host as &lt;em&gt;vlmcsd&lt;/em&gt;. Repeat the test from your PC to see what happens.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Systemd unit (&lt;em&gt;/etc/systemd/system/vlmcsd.service&lt;/em&gt;)&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Unit]
Description=KMS emulator
After=network.target

[Service]
Type=forking
PermissionsStartOnly=true
LimitNOFILE=4096
   
ExecStart=/opt/vlmcsd/bin/vlmcsd -i /opt/vlmcsd/etc/vlmcsd.ini

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;There is no point in leaving this service always online as long as you remember to activate the product every 180 days.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;gvlk&quot;&gt;GVLK&lt;/h3&gt;

&lt;p&gt;KMS recognizes product type by General Volume License Key (GVLK). If you accidentally ignore GVLK during installation or entered the some other keys (i.e. invalid MAK key) afterwards, please restore &lt;a href=&quot;https://technet.microsoft.com/en-us/library/jj612867.aspx&quot;&gt;Windows GVLKs (a.k.a KMS Client Setup Key)&lt;/a&gt;, &lt;a href=&quot;https://technet.microsoft.com/en-us/library/ee624355.aspx&quot;&gt;Office GVLKs&lt;/a&gt;. Open an elevated command prompt on the client Windows:&lt;/p&gt;

&lt;p&gt;For Windows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;slmgr
slmgr /ipk &amp;lt;GVLK&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For Office:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd C:\Program Files\Microsoft Office\Office16
cscript ospp.vbs
cscript ospp.vbs /inpkey:&amp;lt;GVLK&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Choose an approprate GVLK in accord with reference link above. Do &lt;em&gt;*not&lt;/em&gt; fill GVLK in product itself. Always use the command line!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;slmgr&lt;/em&gt; is for Windows OS and usually resides in the &lt;em&gt;system32&lt;/em&gt; directory. &lt;em&gt;ospp.vbs&lt;/em&gt; is for Office 2010/2013/2016. To use it, we should first change the current directory Office&apos;s installation. &lt;em&gt;slmgr.vbs&lt;/em&gt; and &lt;em&gt;cscript ospp.vbs&lt;/em&gt; without parameters print help message.&lt;/p&gt;

&lt;p&gt;You&apos;ll have to install a volume license (VL) version of Office. Office versions downloaded from MSDN and/or Technet are non-VL. If you happened to install a retail licensing product (i.e. OEM, Home, and Ultimate Windows), then in all likelihood KMS is out of your luck. To check Windows version on command line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wmic os get caption
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There exist some inofficial GVLKs for retail licensing Windows, which can be found in &lt;em&gt;vlmcsd.7&lt;/em&gt; man page. Hence, why not attempt to convert Windows to a KMS client as stated above? The only difference is that those inofficial GVLKs hold each activation for 45 or 30 days.&lt;/p&gt;

&lt;p&gt;About Office, if you happened to install a retail version (i.e. Office 16 Pro Plus retail, Visio included), there exists &lt;a href=&quot;https://forums.mydigitallife.net/threads/office-2016-retail-to-vl-a-manual.65616/&quot;&gt;a script&lt;/a&gt; to help you convert the retail version to VOL version. If you have tried to input different MAK keys before the conversion or the product brings in a default MAK key, you should first remove them before KMS activation.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cscript ospp.vbs /dstatus
cscript ospp.vbs /unpkey:&amp;lt;last-5-digits&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You are highly recommended to install and activate Visio 2016 Pro before other office components. &lt;em&gt;inpkey&lt;/em&gt; automatically assigns the keys to Office or Visio.&lt;/p&gt;

&lt;h3 id=&quot;configure-a-client&quot;&gt;Configure a client&lt;/h3&gt;

&lt;p&gt;For Windows OS, &lt;em&gt;skms&lt;/em&gt; means &lt;em&gt;set KMS&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;slmgr.vbs /skms &amp;lt;kms-server[:tcp-port]&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For Office, it is &lt;em&gt;optional&lt;/em&gt; if Windows OS already sets that.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd C:\Program Files\Microsoft Office\Office16
# -or-
cd C:/Program Files(x86)/Microsoft Office/Office16
#
cscript ospp.vbs /sethst:&amp;lt;kms-server&amp;gt;
cscript ospp.vbs /setprt:&amp;lt;tcp-port&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;activate-a-product&quot;&gt;Activate a product&lt;/h3&gt;

&lt;p&gt;After telling a client the KMS address, Windows contacts it for activation on demands. To activate Windows system immediately, right click Computer, select Properties and activate there. Alternatively, do it on command line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;slmgr.vbs /ato
slmgr.vbs /xpr
slmgr.vbs /dlv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Similarly for Office:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cscript ospp.vbs /act
cscript ospp.vbs /dstatus
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;references&quot;&gt;References&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://technet.microsoft.com/en-us/library/jj612867.aspx&quot;&gt;KMS Client Setup Keys&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cnblogs.com/wangchuanyang/p/6397411.html&quot;&gt;使用vlmcsd自建KMS服务~一句命令激活windows/office&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.jsjyhzy.cc/2017/05/kms%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%90%ad%e5%bb%ba/&quot;&gt;KMS服务器搭建&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://dcc.cat/kms.html&quot;&gt;Windows、Office KMS 激活服务器搭建&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.efe.cc/?post=239&quot;&gt;非Windows平台上的仿真KMS服务器&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Linux as Gateway Router</title>
   <link href="/2017/12/29/linux-as-gateway-router/"/>
   <updated>2017-12-29T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/12/29/linux-as-gateway-router</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#principal&quot; id=&quot;markdown-toc-principal&quot;&gt;Principal&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#ip-forwarding-at-layer-3&quot; id=&quot;markdown-toc-ip-forwarding-at-layer-3&quot;&gt;IP Forwarding at Layer 3&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#iptables-forward&quot; id=&quot;markdown-toc-iptables-forward&quot;&gt;Iptables FORWARD&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#iptables-nat&quot; id=&quot;markdown-toc-iptables-nat&quot;&gt;Iptables NAT&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#set-device-gateway&quot; id=&quot;markdown-toc-set-device-gateway&quot;&gt;Set Device Gateway&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#set-the-box&quot; id=&quot;markdown-toc-set-the-box&quot;&gt;Set the Box&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#reference&quot; id=&quot;markdown-toc-reference&quot;&gt;Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;principal&quot;&gt;Principal&lt;/h1&gt;

&lt;p&gt;Suppose a Linux box such as a personal computer has two networking cards (i.e. &lt;em&gt;eth0&lt;/em&gt; and &lt;em&gt;eth1&lt;/em&gt;). One card (i.e. &lt;em&gt;eth0&lt;/em&gt;) connects to the Internet by whatever means like PPoE dial-up, ADSL, static IP etc. The other one (i.e. &lt;em&gt;eth1&lt;/em&gt;) stays within a LAN block.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nowadays, it&apos;s common that a networking card supports two inferfaces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Linux box can serve as a gateway/router for other devices (i.e. virtual machines using NAT mode) LAN with Iptables support. To &lt;a href=&quot;https://serverfault.com/a/431607&quot;&gt;achieve this functionality&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Enable packet forwarding.&lt;/li&gt;
  &lt;li&gt;Iptables FORWARD support.&lt;/li&gt;
  &lt;li&gt;Iptables NAT support.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Actually, what this post does is to set up the routing functionality on Linux boxes, simulating a router.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A layer 3 router maintains a table mapping IPs to ports while a layer 2 switch maintains a table mapping mac addresses to ports. However, a switch learns mac address and port pair by broadcasting packets at first while a router usually needs manual configuration. After a table entry is learned, the switch formards upcoming packet the exact port instead of broadcasting.&lt;/li&gt;
  &lt;li&gt;A Wi-Fi router comprises of two parts, namely a wireless access point and a routing table. The access point handles traffic among WLAN devices while the routing table fowards traffic in and out.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;ip-forwarding-at-layer-3&quot;&gt;&lt;a href=&quot;https://unix.stackexchange.com/a/14058&quot;&gt;IP Forwarding&lt;/a&gt; at Layer 3&lt;/h2&gt;

&lt;p&gt;To server as a gateway, the Linux box must forward a packet not destined for local interfaces (i.e. neither &lt;em&gt;eth0&lt;/em&gt; nor eth1&lt;em&gt;). In this post, such packets are named as &quot;foreign&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If the box receives a packet with destination address not configured locally, it could either drop or forward it. It is intuitive to drop a strange packet. Alternatively, the box (i.e. router) may choose to forward the packet to some interface letting the packet traverse it as a router usually resides across between multiple network blocks.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;forwarding&lt;/em&gt; is a synonym for &lt;em&gt;routing&lt;/em&gt; meaning forwarding a foreign packet according to &lt;em&gt;routing tables&lt;/em&gt; similar to routing locally generated packets. In other words, packet forwarding is routing tables&apos; business and has nothing to do with Iptables.&lt;/p&gt;

&lt;p&gt;Read more at &lt;a href=&quot;https://serverfault.com/q/248841&quot;&gt;IP Forwarding = when and why is this required?&lt;/a&gt;. It is basically for inter-network (except for VLAN router) packet transmission and not for that of inter-interface. If two interfaces are on the same network then IP forwarding is not involved (rare case though). Additionally, if one is virtual interface, IP forwarding is not needed either.&lt;/p&gt;

&lt;p&gt;For example, traffic between two devices on the same network does not require forwarding/routing at layer 3. Instead, it is handled at layer 2 by switches, access points of Wi-Fi router, or direct Ethernet wire.&lt;/p&gt;

&lt;p&gt;The box should enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net.ipv4.ip_forward&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;iptables-forward&quot;&gt;Iptables FORWARD&lt;/h2&gt;

&lt;p&gt;Once forwarded, the foreign packet will be examined by FORWARD chain of Iptables. Please be noted, keyword FORWARD is not meant to forward a packet but apply Iptables rules against the forwarded packets from routing tables.&lt;/p&gt;

&lt;p&gt;The box should allow forwarded packets to go outside by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-j ACCEPT&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;iptables-nat&quot;&gt;Iptables NAT&lt;/h2&gt;

&lt;p&gt;Before a foreign packet is forwarded outside, the box should also modify the source IP to that of the outgoing interface (i.e. &lt;em&gt;eth0&lt;/em&gt;), namely to set up NAT by Iptables.&lt;/p&gt;

&lt;p&gt;After examined by Iptables FORWARD, the source IP remains of the original one (that of the foreign device). If it is left alone, the destination device would attempt to send back packets directly to the foreign device without intervention of the box.&lt;/p&gt;

&lt;p&gt;Iptables NAT support will maintain an kernel mapping between the source IP and that of outgoing interface, such that destination device can reply to the box instead.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-j MASQUERADE&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-j SNAT&lt;/code&gt; should be enabled.&lt;/p&gt;

&lt;h1 id=&quot;set-device-gateway&quot;&gt;Set Device Gateway&lt;/h1&gt;

&lt;p&gt;Set LAN devices&apos; gateway to IP of &lt;em&gt;eth1&lt;/em&gt; on the box.&lt;/p&gt;

&lt;p&gt;For Linux device, this can be done with &lt;em&gt;ip route&lt;/em&gt; or &lt;em&gt;route&lt;/em&gt; command line. Say LAN block is &lt;em&gt;192.168.10.0/24&lt;/em&gt; while &lt;em&gt;192.168.10.1&lt;/em&gt; is IP of &lt;em&gt;eth1&lt;/em&gt; of the box.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# ip route add default 192.168.10.0/24 via 192.168.10.1 dev eth1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# route add 192.168.10.0 netmask 255.255.255.0 gw 192.168.10.1 dev eth1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is not unusual that home devices&apos; (i.e. smartphone) default gateway is set to &lt;em&gt;192.168.0.1&lt;/em&gt; (IP of Wi-Fi router).&lt;/p&gt;

&lt;h1 id=&quot;set-the-box&quot;&gt;Set the Box&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Enable IP forwarding.&lt;/p&gt;

    &lt;p&gt;It simply determines behaviour when receiving a packet for another network. Without forwarding, the packet is dropped. With forwarding, routing tables are consulted to determine to which interface it should be forwarded.&lt;/p&gt;

    &lt;p&gt;Permanent across reboots:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# echo &apos;net.ipv4.ip_forward=1&apos; &amp;gt; /etc/sysctl.d/20-ip_forward.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;For current session:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# sysctl -w net.ipv4.ip_forward=1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# sysctl -p /etc/sysctl.d/20-ip_forward.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Check&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# cat /proc/sys/net/ipv4/ip_forward&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable Iptables FORWARD&lt;/p&gt;

    &lt;p&gt;Please be noted locally generated packets are not examined by FORWARD chains.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This FORWARD rule lets forwarded packets go outside.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable Iptables NAT&lt;/p&gt;

    &lt;p&gt;Turn on &lt;a href=&quot;http://www.tldp.org/HOWTO/IP-Masquerade-HOWTO/index.html&quot;&gt;MASQUERADE NAT&lt;/a&gt; on the box. Generally, MASQUERADE is required when many LAN private IPs&apos; traffic sits behind and goes through a public single IP (i.e. Wi-Fi router), namely a many-to-one relationship.&lt;/p&gt;

    &lt;p&gt;Needless to say, Iptables NAT should be accomplished by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t nat&lt;/code&gt; table.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE (poor NAT)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source &amp;lt;IP of eth0&amp;gt; (better NAT)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Read more on &lt;a href=&quot;/2017/12/12/wireshark/&quot;&gt;Wireshark post&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://how-to.wikia.com/wiki/How_to_set_up_a_NAT_router_on_a_Linux-based_computer&quot;&gt;NAT gateway&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.yolinux.com/TUTORIALS/LinuxTutorialIptablesNetworkGateway.html&quot;&gt;LinuxTutorialIptablesNetworkGateway&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Wireshark</title>
   <link href="/2017/12/12/wireshark/"/>
   <updated>2017-12-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/12/12/wireshark</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#permission&quot; id=&quot;markdown-toc-permission&quot;&gt;Permission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tutorials&quot; id=&quot;markdown-toc-tutorials&quot;&gt;Tutorials&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#android&quot; id=&quot;markdown-toc-android&quot;&gt;Android&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#androiddump&quot; id=&quot;markdown-toc-androiddump&quot;&gt;androiddump&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#nat-gateway&quot; id=&quot;markdown-toc-nat-gateway&quot;&gt;NAT gateway&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#proxy&quot; id=&quot;markdown-toc-proxy&quot;&gt;Proxy&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#alternatives&quot; id=&quot;markdown-toc-alternatives&quot;&gt;Alternatives&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# echo &apos;net-analyzer/wireshark androiddump&apos; &amp;gt;&amp;gt; /etc/portage/package.use/wireshark&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt wireshark&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;permission&quot;&gt;Permission&lt;/h1&gt;

&lt;p&gt;Running Wireshark in &lt;em&gt;root&lt;/em&gt; account is dangerous. We can add normal user account into &lt;em&gt;wireshark&lt;/em&gt; group.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# gpasswd -a username wireshark&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should log out and log in back to take effect. &lt;em&gt;newgrp&lt;/em&gt; log in to a new group in current shell:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;newgrp wireshark
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wireshark-gtk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then launch Wireshark from terminal directly.&lt;/p&gt;

&lt;h1 id=&quot;tutorials&quot;&gt;Tutorials&lt;/h1&gt;

&lt;p&gt;to-dos&lt;/p&gt;

&lt;h1 id=&quot;android&quot;&gt;Android&lt;/h1&gt;

&lt;p&gt;It&apos;s recommended to install terminal emulator app such as Termux.&lt;/p&gt;

&lt;h3 id=&quot;androiddump&quot;&gt;&lt;a href=&quot;https://www.wireshark.org/docs/man-pages/androiddump.html&quot;&gt;androiddump&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;androiddump&lt;/em&gt; as explained by the term name, is used to capture Android system &lt;em&gt;logcat&lt;/em&gt; messages and networking flow. Before the capture carried out, you should provide the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Android SDK tools (i.e. &lt;em&gt;adb&lt;/em&gt;) are added to PATH variable (for &lt;em&gt;logcat&lt;/em&gt; capture);&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.androidtcpdump.com/&quot;&gt;Android &lt;em&gt;tcpdump&lt;/em&gt;&lt;/a&gt; on a &lt;em&gt;rooted&lt;/em&gt; device (for networking flow). Device vendor may have enclosed &lt;em&gt;tcpdump&lt;/em&gt; in Android image.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;tcpdump&lt;/em&gt; captures Android traffic and then pass it to Wireshark on your PC. &lt;em&gt;androiddump&lt;/em&gt; serves as the bridge between &lt;em&gt;tcpdump&lt;/em&gt; and Wireshark.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Obviously, your device should be in Developer Debugging mode and recognized by SDK tools.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;tcpdump&lt;/em&gt; requires root permission (rooted device), exposing to maleware attack.&lt;/p&gt;

&lt;h3 id=&quot;nat-gateway&quot;&gt;&lt;a href=&quot;http://how-to.wikia.com/wiki/How_to_set_up_a_NAT_router_on_a_Linux-based_computer&quot;&gt;NAT gateway&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Set PC as gateway router to your device. Then use Wireshark to capture PC Wi-Fi interface. Without explicit pointing out, I use &lt;em&gt;router&lt;/em&gt; and &lt;em&gt;gateway&lt;/em&gt; interchangeably in this section.&lt;/p&gt;

&lt;p&gt;Here is my case. Linux and Android connect to the same Wi-Fi as follows:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Device&lt;/th&gt;
      &lt;th&gt;IP&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Linux&lt;/td&gt;
      &lt;td&gt;192.168.0.150&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Android&lt;/td&gt;
      &lt;td&gt;192.168.0.151&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Router&lt;/td&gt;
      &lt;td&gt;192.168.0.1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;WAN&lt;/td&gt;
      &lt;td&gt;dial-up&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;By default Linux and Android uses gateway &lt;em&gt;192.168.0.1&lt;/em&gt;. We can check route by:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;route &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ip route
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Firstly, we set Android Wi-Fi gateway to Linux&apos;s IP &lt;em&gt;192.168.0.150&lt;/em&gt;. Do this in Android Wi-Fi setting. Thus all Android Wi-Fi data routes through Linux.&lt;/p&gt;

&lt;p&gt;Then on Linux, we should configure NAT for Android traffic, forwarding Android traffic to the real Wi-Fi gateway &lt;em&gt;192.168.0.1&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# sysctl -w net.ipv4.ip_forward=1&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# iptables -A FORWARD -i wlan0 -j ACCEPT&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE (poor NAT)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# iptables -t nat -A POSTROUTING -o wlan0 -j SNAT --to-source 192.168.0.150 (better NAT)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;NAT requires IP forwarding that, by default, is disabled in Linux boxes.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;MASQUERADE replaces the sender&apos;s (Android device &lt;em&gt;192.168.0.151&lt;/em&gt; here) address by the router&apos;s (Linux PC &lt;em&gt;192.168.0.150&lt;/em&gt; here) address.&lt;/p&gt;

    &lt;p&gt;As the router here is Linux PC, we&apos;d &lt;a href=&quot;https://unix.stackexchange.com/q/21967&quot;&gt;better&lt;/a&gt; use SNAT istead. Bascially, we use SNAT for static router IP, improving Iptables performance. However, MASQUERADE is a &lt;em&gt;must&lt;/em&gt; when the router connects to the Internet with PPoE dial-up (different WAN IP each dial-up).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;This is a special case of the reference as there is only one Linux interface (&lt;em&gt;wlan0&lt;/em&gt;) for both LAN and WAN communication. Please read more details via &lt;a href=&quot;http://www.yolinux.com/TUTORIALS/LinuxTutorialIptablesNetworkGateway.html&quot;&gt;LinuxTutorialIptablesNetworkGateway&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;We can &lt;em&gt;omit&lt;/em&gt; the MASQUERADE or SNAT part because Wi-Fi router can reach Android device directly without Linux &lt;em&gt;wlan0&lt;/em&gt; NAT support.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To check the setup, make sure Android connect to network (ping in Termux). Further more, we can check Iptables counts:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# iptables -L -nv [-t nat]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Android outgoing traffic flow is as follows:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Android -&amp;gt; Router NAT -&amp;gt; Linux NAT -&amp;gt; Router NAT -&amp;gt; The WAN Internet&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Router NAT handles LAN communication while Linux NAT handles Android traffic mapping. For incoming traffic, just reverse the arrow.&lt;/p&gt;

&lt;p&gt;Finally, Wireshark can capture Android traffic on PC. We can print out only Android traffic by filtering the Android IP:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;ip.addr == 192.168.0.151&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you choose to omit the MASQUERADE or SNAT part, Wireshark can only caputre traffic from Android while miss traffic to it. Meanwhile, the reverse traffic flow resembles the usual:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;the WAN Internet -&amp;gt; Router NAT -&amp;gt; Android&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;proxy&quot;&gt;Proxy&lt;/h3&gt;

&lt;p&gt;Set up a proxy (i.e. OpenVPN, Privoxy HTTP etc.) on PC and proxy device traffic through.&lt;/p&gt;

&lt;h3 id=&quot;alternatives&quot;&gt;Alternatives&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;tPacketCapture app based on Android VPN service.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/JZ-Darkal/AndroidHttpCapture&quot;&gt;AndroidHttpCapture&lt;/a&gt; app for HTTP(s) capture.&lt;/li&gt;
  &lt;li&gt;We can use Charles and Fiddler for HTTP(s) capture.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Solutions based on VPN service can capture transmission layer packets. Most tools above only capture HTTP(s) layer traffic.&lt;/p&gt;

&lt;p&gt;Above all, the most convenient method is running &lt;em&gt;tshark&lt;/em&gt; (Wireshark terminal counterpart) on Wi-Fi router (i.e. OpenWrt).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>archlinux</title>
   <link href="/2017/11/28/archlinux/"/>
   <updated>2017-11-28T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/11/28/archlinux</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#installation-guide&quot; id=&quot;markdown-toc-installation-guide&quot;&gt;Installation guide&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#usb-stick&quot; id=&quot;markdown-toc-usb-stick&quot;&gt;USB Stick&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#usb-booting&quot; id=&quot;markdown-toc-usb-booting&quot;&gt;USB Booting&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#time-and-network&quot; id=&quot;markdown-toc-time-and-network&quot;&gt;Time and Network&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#bios-gpt-scheme&quot; id=&quot;markdown-toc-bios-gpt-scheme&quot;&gt;BIOS GPT scheme&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#partitioning&quot; id=&quot;markdown-toc-partitioning&quot;&gt;Partitioning&lt;/a&gt;            &lt;ol&gt;
              &lt;li&gt;&lt;a href=&quot;#swap&quot; id=&quot;markdown-toc-swap&quot;&gt;Swap&lt;/a&gt;&lt;/li&gt;
            &lt;/ol&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#filesystem&quot; id=&quot;markdown-toc-filesystem&quot;&gt;Filesystem&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#mount&quot; id=&quot;markdown-toc-mount&quot;&gt;Mount&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#uefi-gpt-scheme&quot; id=&quot;markdown-toc-uefi-gpt-scheme&quot;&gt;UEFI GPT scheme&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#disk-preparation&quot; id=&quot;markdown-toc-disk-preparation&quot;&gt;Disk Preparation&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#erase-disk&quot; id=&quot;markdown-toc-erase-disk&quot;&gt;Erase Disk&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#gpt-table&quot; id=&quot;markdown-toc-gpt-table&quot;&gt;GPT Table&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#partitioning-1&quot; id=&quot;markdown-toc-partitioning-1&quot;&gt;Partitioning&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#esp-filesystem&quot; id=&quot;markdown-toc-esp-filesystem&quot;&gt;ESP Filesystem&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#luks&quot; id=&quot;markdown-toc-luks&quot;&gt;LUKS&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#lvm&quot; id=&quot;markdown-toc-lvm&quot;&gt;LVM&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#filesystem-1&quot; id=&quot;markdown-toc-filesystem-1&quot;&gt;Filesystem&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#mounting&quot; id=&quot;markdown-toc-mounting&quot;&gt;Mounting&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mirrors&quot; id=&quot;markdown-toc-mirrors&quot;&gt;Mirrors&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#base-group&quot; id=&quot;markdown-toc-base-group&quot;&gt;base group&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#fstab&quot; id=&quot;markdown-toc-fstab&quot;&gt;fstab&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#copy-keyfile&quot; id=&quot;markdown-toc-copy-keyfile&quot;&gt;Copy Keyfile&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#chroot&quot; id=&quot;markdown-toc-chroot&quot;&gt;Chroot&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#time&quot; id=&quot;markdown-toc-time&quot;&gt;Time&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#localization&quot; id=&quot;markdown-toc-localization&quot;&gt;Localization&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#network&quot; id=&quot;markdown-toc-network&quot;&gt;Network&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#initramfs-by-mkinitcpio&quot; id=&quot;markdown-toc-initramfs-by-mkinitcpio&quot;&gt;Initramfs by mkinitcpio&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#root-password&quot; id=&quot;markdown-toc-root-password&quot;&gt;root password&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#boot-loader---grub&quot; id=&quot;markdown-toc-boot-loader---grub&quot;&gt;Boot loader - Grub&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#reboot&quot; id=&quot;markdown-toc-reboot&quot;&gt;Reboot&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#general-settings&quot; id=&quot;markdown-toc-general-settings&quot;&gt;General Settings&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#x&quot; id=&quot;markdown-toc-x&quot;&gt;X&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#time-1&quot; id=&quot;markdown-toc-time-1&quot;&gt;Time&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pacman&quot; id=&quot;markdown-toc-pacman&quot;&gt;pacman&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#aur&quot; id=&quot;markdown-toc-aur&quot;&gt;AUR&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#xterm&quot; id=&quot;markdown-toc-xterm&quot;&gt;Xterm&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#copy-and-paste&quot; id=&quot;markdown-toc-copy-and-paste&quot;&gt;Copy and Paste&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#alacritty&quot; id=&quot;markdown-toc-alacritty&quot;&gt;Alacritty&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#resolution&quot; id=&quot;markdown-toc-resolution&quot;&gt;Resolution&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#virtual-terminal&quot; id=&quot;markdown-toc-virtual-terminal&quot;&gt;Virtual terminal&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#xorg&quot; id=&quot;markdown-toc-xorg&quot;&gt;Xorg&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#fcitx&quot; id=&quot;markdown-toc-fcitx&quot;&gt;Fcitx&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wps&quot; id=&quot;markdown-toc-wps&quot;&gt;WPS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#alsa&quot; id=&quot;markdown-toc-alsa&quot;&gt;ALSA&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation-guide&quot;&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Installation_guide&quot;&gt;Installation guide&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Arch Linux has dropped support for &lt;em&gt;i686&lt;/em&gt; platforms. Only &lt;em&gt;x86_64&lt;/em&gt; now!&lt;/li&gt;
  &lt;li&gt;Download the latest ISO image from &lt;a href=&quot;https://www.archlinux.org/download/&quot;&gt;download link&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Install necessary packages. At least &lt;em&gt;wpa_supplicant&lt;/em&gt; as the &lt;em&gt;base&lt;/em&gt; group does not include that.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;usb-stick&quot;&gt;USB Stick&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;dd&lt;/em&gt; command will be used to create the bootable stick as it is more reliable and also the recommended method on the Wiki page. &lt;em&gt;dd&lt;/em&gt; erases the whole USB stick and treats it as a hard drive.&lt;/p&gt;

&lt;p&gt;Without explict notice, we assume the USB drive to be &lt;em&gt;/dev/sdb&lt;/em&gt;. &lt;em&gt;dd&lt;/em&gt; command is effective but dangerous as well. It take effects immediately without confirmation prompt. Therefore, please make sure you select the exact &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;of=&lt;/code&gt; argument.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;# fdisk -l; blkid; lsblk -f; findmnt&lt;/span&gt;
root@archiso / &lt;span class=&quot;c&quot;&gt;# dd bs=1M if=/path/to/archlinux.iso of=/dev/sdb status=progress oflag=sync&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The optimal block size &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bs&lt;/code&gt; argument is determined by various factors (both hardware and software) on the system. Empirically, 1M or 4M is good enough.&lt;/p&gt;

&lt;p&gt;To restore the USB stick as normal data storage, we should remove the ISO 9660 filesystem signature before re-partitioning and re-formating the USB drive by &lt;em&gt;wipefs&lt;/em&gt; command. It only erase signatures of filesystem, raid  or partition-table while leave filesystem itself untouched.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;# wipefs --all /dev/sdb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;usb-booting&quot;&gt;USB Booting&lt;/h2&gt;

&lt;p&gt;Disable &lt;em&gt;secure boot&lt;/em&gt; in BIOS setting as most Linux distributions do not buy digital certifits from Verisign.&lt;/p&gt;

&lt;p&gt;If the USB stick refuses to load, then try the &lt;a href=&quot;#usb-stick&quot;&gt;dd command&lt;/a&gt; once more. If directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/sys/firmware/efi/efivars&lt;/code&gt; exists, then it&apos;s booted in UEFI mode, otherwise it is in legacy BIOS mode.&lt;/p&gt;

&lt;p&gt;By default, Arch ISO uses Zsh shell. To log all commands, set in &lt;em&gt;~/.zshrc&lt;/em&gt; the following to empty string:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;HISTSIZE=-1
HISTFILESIZE=-1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source .zshrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Within the Live system, we use Alt-&lt;em&gt;arrow&lt;/em&gt; or Ctrl-Alt-Fx to switch virtual console and read installation guide there.&lt;/p&gt;

&lt;h2 id=&quot;time-and-network&quot;&gt;Time and Network&lt;/h2&gt;

&lt;p&gt;Once booted into the live system, check network connection and rectify system clock:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# ping www.archlinux.org&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# timedatectl set-ntp true; timedatectl set-timezone Asia/Shanghai; timedatectl status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For wired/wireless network that require captive login or user agreement, refer to &lt;a href=&quot;https://superuser.com/q/132392&quot;&gt;Using command line to connect to a wireless network with an http login&lt;/a&gt; and &lt;a href=&quot;https://bbs.archlinux.org/viewtopic.php?id=187511&quot;&gt;Connecting to a Wireless network with a captive portal&lt;/a&gt;. Also, please check &lt;a href=&quot;#network&quot;&gt;network&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;bios-gpt-scheme&quot;&gt;BIOS GPT scheme&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Grub bootloader.&lt;/li&gt;
  &lt;li&gt;BIOS/GPT &lt;a href=&quot;https://wiki.archlinux.org/index.php/Partitioning&quot;&gt;partitioning&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Single &lt;em&gt;root&lt;/em&gt; partition plus extra &lt;em&gt;swap file&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This booting schema is only used with VMs in &lt;a href=&quot;https://www.zhstar.win/2015/08/21/virtualbox/&quot;&gt;VirtualBox&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;partitioning&quot;&gt;Partitioning&lt;/h3&gt;

&lt;p&gt;Firstly, to identify disk devices:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# fdisk -l&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# lsblk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For &quot;Grub, BIOS/GPT&quot; scheme, we must create the &lt;a href=&quot;https://wiki.archlinux.org/index.php/BIOS_boot_partition&quot;&gt;BIOS boot partition&lt;/a&gt; to hold Grub &lt;em&gt;core.img&lt;/em&gt;. Around 1 MiB (2048 sectors) is enough. Partition number can be in any position order but has to be on the first 2 TiB of the disk. This partition should be flagged as &lt;em&gt;bios_grub&lt;/em&gt; for &lt;em&gt;parted&lt;/em&gt;, &lt;em&gt;ef02&lt;/em&gt; for &lt;em&gt;gdisk&lt;/em&gt;, or select &lt;em&gt;BIOS boot&lt;/em&gt; and partition type &lt;em&gt;4&lt;/em&gt; for &lt;em&gt;fdisk&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, &quot;Grub, BIOS/MBR&quot; scheme uses post-MBR gap (after the 512B MBR and before the first partition) to store &lt;em&gt;core.img&lt;/em&gt;. Usually this gap is 31 KiB. For complex modules in &lt;em&gt;core.img&lt;/em&gt;, this space is limited. That can be resolved by pushing forward starting sector of the first parititon. For instance, partitioning tool can align at MiB boundaries, thus leaving enough post-MBR gap. So, it eliminates the bother to create BIOS boot partition.&lt;/p&gt;

&lt;p&gt;Here is the partitioning steps:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ # parted -a optimal /dev/sda
(parted) help
(parted) mktable gpt
(parted) unit s
(parted) print free
(parted) mkpart primary 0% 2047s        # 1MiB 2047s
(parted) set 1 bios_grub on
(parted) mkpart primary 2048s 100%
(parted) print free
(parted) quit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Tell &lt;em&gt;parted&lt;/em&gt; to optimally align at 1MiB boundaries.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;By default, GPT&apos;s free sector starts at 34s (equally &lt;em&gt;0%&lt;/em&gt;). Make BIOS boot partition be the very first parition which starts at &lt;em&gt;34s&lt;/em&gt; spanning to &lt;em&gt;2047s&lt;/em&gt;. &lt;em&gt;parted&lt;/em&gt; reminds:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Warning: The resulting partition is not properly aligned for best performance. Ignore/Cancel?&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Choose &lt;em&gt;Ignore&lt;/em&gt; as this partition will not be regularly accessed. Performance issues can be disregarded though this is out of GPT alignment specifications.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;The rest space is assigned to &lt;em&gt;root&lt;/em&gt; starting at &lt;em&gt;2048s&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;swap&quot;&gt;Swap&lt;/h4&gt;

&lt;p&gt;There is not any other separate partitions except that a &lt;em&gt;swap file&lt;/em&gt; will be created. Swap partition bears NO advantages over swap file but could be shared among different systems. On the other hand, we can easily resize and plug/unplug a swap file on-the-fly.&lt;/p&gt;

&lt;p&gt;Leave the swap file part after booting into new system.&lt;/p&gt;

&lt;h3 id=&quot;filesystem&quot;&gt;Filesystem&lt;/h3&gt;

&lt;p&gt;There is no need to create file system for the partition &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bios_grub&lt;/code&gt;. Hence, just create an &lt;em&gt;ext4&lt;/em&gt; on the single &lt;em&gt;root&lt;/em&gt; parition:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mkfs.ext4 /dev/sda2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;mount&quot;&gt;Mount&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mount /dev/sda2 /mnt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As there is only the &lt;em&gt;root&lt;/em&gt; parition, we would not create any other mount points under &lt;em&gt;/mnt&lt;/em&gt;, neither &lt;em&gt;/home&lt;/em&gt; nor &lt;em&gt;/boot&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;uefi-gpt-scheme&quot;&gt;UEFI GPT scheme&lt;/h2&gt;

&lt;p&gt;Almost all modern systems take UEFI booting schema. The old BIOS legacy mode discussed above is almost deprecated. To set the PC booting in only UEFI mode in BIOS setting (disable legacy BIOS). Also make sure the ISO is &lt;a href=&quot;#usb-booting&quot;&gt;booted in UEFI mode&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;disk-preparation&quot;&gt;Disk Preparation&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;If LVM, system encrytion (LUKS), or RAID is desired, do it now.&lt;/li&gt;
  &lt;li&gt;ESP could be any of FAT12, FAT16, FAT32 and VFAT (preferred).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will erase partition or the whole drive before partitioning and formating.&lt;/p&gt;

&lt;h3 id=&quot;erase-disk&quot;&gt;Erase Disk&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;This section only covers normal mechanical disk drives. For SSDs, it is a different story.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We want to securely &lt;a href=&quot;https://wiki.archlinux.org/index.php/Dm-crypt/Drive_preparation#Secure_erasure_of_the_hard_disk_drive&quot;&gt;erase the&lt;/a&gt; disk by overwritting the entire drive with random data. There are a host of &lt;a href=&quot;https://wiki.archlinux.org/index.php/Securely_wipe_disk&quot;&gt;general methods&lt;/a&gt; available. But I choose the &lt;em&gt;dm-crypt&lt;/em&gt; specific method here. Optionally, you could either erase just a single partition (i.e. &lt;em&gt;/dev/sdXY&lt;/em&gt;) or the complete drive (i.e. &lt;em&gt;/dev/sdX&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;We first create a temporary &lt;em&gt;dm-crypt&lt;/em&gt; container:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# erase a partition
root@archiso ~ # cryptsetup open /dev/sda1 --type plain --key-file /dev/urandom to_be_wiped
# erase a disk
root@archiso ~ # cryptsetup open /dev/sda --type plain --key-file /dev/urandom to_be_wiped
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--key-file /dev/urandom&lt;/code&gt; is used as the encryption key. The container device is located at &lt;em&gt;/dev/mapper/to_be_wipded&lt;/em&gt;. We can verify its existence by &lt;em&gt;lsblk&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Next, we fill the container with zeros without the need of &lt;em&gt;/dev/urandom&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# dd bs=1M if=/dev/zero of=/dev/mapper/to_be_wiped status=progress&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For a large (i.e. a multi-terabyte disk) drive or partition, this may take hours or even a day.&lt;/p&gt;

&lt;p&gt;Finally, close the temporary container:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cryptsetup close /dev/mapper/to_be_wipded&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# lsblk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;gpt-table&quot;&gt;GPT Table&lt;/h3&gt;

&lt;p&gt;Use &lt;em&gt;parted&lt;/em&gt; to create GPT table:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# parted -a opt /dev/sda&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mklabel gpt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;partitioning-1&quot;&gt;Partitioning&lt;/h3&gt;

&lt;p&gt;For future compatability and scability, create an extra BIOS boot partition (for Grub). Additionally, I want the &lt;em&gt;/boot&lt;/em&gt; partition also encrypted. This setup really makes the system complicated. Anyway, the practice and security improvement deserve it!&lt;/p&gt;

&lt;p&gt;Here is the &lt;a href=&quot;https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#Encrypted_boot_partition_(GRUB)&quot;&gt;partitioning steps&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# parted -a opt /dev/sda&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; unit s/MiB
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p free
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary 30s/40s 2047s
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; toggle 1 bios_grub
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary fat32 2048s/1MiB 551MiB
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; toggle 2 esp/boot
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary 551MiB 751MiB
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary 751MiB 100%
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; print free
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;As the Grub BIOS boot partition is not regularly accessed, there is no need to follow rigid alignment rules. It can just start at 34s (no alignment) or 40s (minimal alignment).&lt;/p&gt;

    &lt;p&gt;GRUB embeds its &lt;em&gt;core.img&lt;/em&gt; into this partition&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;It is &lt;a href=&quot;https://www.rodsbooks.com/efi-bootloaders/principles.html&quot;&gt;recommended&lt;/a&gt;. to create the ESP with 550MiB.&lt;/li&gt;
  &lt;li&gt;When the unit used if MiB, the end of part 2 and the start of part 3 are both 551MiB. If using &lt;em&gt;s&lt;/em&gt; unit, their relation should be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+1&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Up to now, the partitions layout looks like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/dev/sda1: BIOS boot
/dev/sda2: ESP
/dev/sda3: boot LUKS
/dev/sda4: &apos;/&apos;, &apos;/home&apos;, and &apos;/swap&apos; LUKS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;esp-filesystem&quot;&gt;ESP Filesystem&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mkfs.vfat -F32 /dev/sda2&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# parted /dev/sda p free ; fdisk -l /dev/sda&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;BIOS boot partition shall not be formated or mounted. Just leave it alone.&lt;/li&gt;
  &lt;li&gt;Both &lt;em&gt;sda3&lt;/em&gt; and &lt;em&gt;sda4&lt;/em&gt; will be encrypted by LUKS, so there is no need to create filesystem at this stage.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;luks&quot;&gt;LUKS&lt;/h3&gt;

&lt;p&gt;As Grub does not support LUKS2, use LUSK1 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--type luks1&lt;/code&gt;) on &lt;em&gt;/dev/sda3&lt;/em&gt; for &lt;em&gt;/boot&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Firstly, we create a passphrase-protected file by &lt;em&gt;gpg&lt;/em&gt; (namely &lt;em&gt;arch-luks.gpg&lt;/em&gt;) that will be used to to encrypt the LUKS container.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# export GPG_TTY=$(tty)&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# dd if=/dev/urandom bs=8388607 count=1 | gpg -v --symmetric --cipher-algo AES256 --armor --output ~/arch-luks.gpg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bs=8388607 count=1&lt;/code&gt;? Because the maximum key file size is 8192KiB. From the empirics of &lt;a href=&quot;https://www.zhstar.win/2015/09/10/lvm-luks-lvm/&quot;&gt;Gentoo installation&lt;/a&gt;, we should decrease the maximum value by 1.&lt;/p&gt;

&lt;p&gt;Before anything else, make a backup of the key file (i.e. to a USB stick), as otherwise the Live environment would lose it upon reboot.&lt;/p&gt;

&lt;p&gt;Next, we create the LUKS &lt;em&gt;container&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# gpg --decrypt ~/arch-luks.gpg | cryptsetup luksFormat -v --type luks1 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --key-file - --use-random /dev/sda3&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# gpg --decrypt ~/arch-luks.gpg | cryptsetup luksFormat -v --type luks2 --cipher aes-xts-plain64 --key-size 512 --hash sha512 --key-file - --use-random /dev/sda4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;luksFormat&lt;/em&gt; does not format the device, but sets up the &lt;em&gt;header&lt;/em&gt; part of the LUKS container. Specially it encrypts the &lt;em&gt;master key&lt;/em&gt; and embeds it into the header.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Master key is randomly choosen upon container creation and, encrypted and embedded in the header part.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is the master key&apos;s job to encrypt the data on partition. Key file or passphrase is only used to &lt;a href=&quot;https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions&quot;&gt;encrypt/decrypt the master key&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For safety, add a fallback passphrase in addition to the key file. It always asks for an existing passphrase or key file before adding a new one.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cryptsetup luksAddKey -v --key-file arch-luks --iter-time 5000 /dev/sda3 --key-slot 0&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cryptsetup luksAddKey -v --key-file arch-luks --iter-time 5000 /dev/sda4 --key-slot 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Apart from &lt;em&gt;luksAddKey&lt;/em&gt;, we can also &lt;em&gt;luksRemoveKey&lt;/em&gt;, &lt;em&gt;luksKillSlot&lt;/em&gt; etc.&lt;/p&gt;

&lt;p&gt;We can use &lt;em&gt;luksDump&lt;/em&gt; command to check the LUKS header:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cryptsetup luksDump /dev/sda3&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cryptsetup luksDump /dev/sda4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It&apos;s better to backup the LUKS header:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cryptsetup luksHeaderBackup /dev/sda3 --header-backup-file ~/sda3-luks-header.img&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cryptsetup luksHeaderBackup /dev/sda4 --header-backup-file ~/sda4-luks-header.img&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of course, we have a counterpart command &lt;em&gt;luksHeaderRestore&lt;/em&gt; to restore header file. Once backuped, the the LUKS header may be deleted from the container. Details, refer to Arch wiki.&lt;/p&gt;

&lt;p&gt;Once created, it is time to &lt;em&gt;open&lt;/em&gt; the containers. The first open command, uses the fallback passphrase while the second uses key file.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cryptsetup open /dev/sda3 cryptboot&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cryptsetup --key-file ~/arch-luks open /dev/sda4 cryptlvm&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# lsblk&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# ls -al /dev/mapper/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;open&lt;/em&gt; command asks for key file or passphrase to decrypt the master key in the LUKS header. The decrypted master key is then used to decrypte the LUKS container. The decrypted containers are now available at &lt;em&gt;/dev/mapper/&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;lvm&quot;&gt;LVM&lt;/h3&gt;

&lt;p&gt;LUKS containers are ready for LVM containers on which we then create Arch Linux filesystem.&lt;/p&gt;

&lt;p&gt;At this stage, we only care about &lt;em&gt;/dev/mapper/cryptlvm&lt;/em&gt; as there is no LVM requirement on &lt;em&gt;/dev/mapper/cryptboot&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# pvcreate /dev/mapper/cryptlvm ; pvdisplay -v -m&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# vgcreate volgrp /dev/mapper/cryptlvm ; vgdisplay -v&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# lvcreate --size 16G volgrp --name swap&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# lvcreate --size 60G volgrp --name root&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# lvcreate --size 250G volgrp --name home ; lvdisplay -v -m&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# ls -al /dev/{mapper,volgrp}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Create a physical volume &lt;em&gt;/dev/mapper/cryptlvm&lt;/em&gt; on top of the LUKS container.&lt;/li&gt;
  &lt;li&gt;Create a volume group &lt;em&gt;volgrp&lt;/em&gt; and add the physical volume into it. We can add more, if multiple physical volumes exist.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create logical volumes within &lt;em&gt;volgrp&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;For futher compatibility, leave some &lt;em&gt;volgrp&lt;/em&gt; space unallocated. Size of logical volumes can be ajusted on the fly.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Created logical volmes&apos; symbolic links reside in two equivalent locations, namely &lt;em&gt;/dev/mapper/&lt;/em&gt; and &lt;em&gt;/dev/volgrp/&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;filesystem-1&quot;&gt;Filesystem&lt;/h3&gt;

&lt;p&gt;Format the logical volumes.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mkswap /dev/volgrp/swap&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mkfs.ext4 /dev/volgrp/root&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mkfs.ext4 /dev/volgrp/home&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Recall that, we have not create filesystem for the decrypted &lt;em&gt;cryptboot&lt;/em&gt; yet. Just create filesystem on top LUKS container directly without LVM.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mkfs.ext2 /dev/mapper/cryptboot&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# lsblk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;mounting&quot;&gt;Mounting&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# blkid&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# swapon /dev/volgrp/swap&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mount /dev/volgrp/root /mnt&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mkdir /mnt/home; mount /dev/volgrp/home /mnt/home&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mkdir /mnt/boot; mount /dev/mapper/cryptboot /mnt/boot&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# mkdir /mnt/efi; mount /dev/sda2 /mnt/efi&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# lsblk&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Before mounting, we should use &lt;em&gt;blkid&lt;/em&gt; to check relevant partition and filesystem are correctly prepared.&lt;/li&gt;
  &lt;li&gt;LUKS boot partition can be mounted directly as we have already create the filesystem on it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;mirrors&quot;&gt;Mirrors&lt;/h2&gt;

&lt;p&gt;Get a state-of-the-art copy from &lt;a href=&quot;https://www.archlinux.org/mirrorlist/&quot;&gt;mirrorlist generator&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-vo&lt;/span&gt; mirrorlist https://www.archlinux.org/mirrorlist/?country&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;all&amp;amp;protocol&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;http&amp;amp;protocol&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;https&amp;amp;ip_version&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4&amp;amp;ip_version&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Edit &lt;em&gt;/etc/pacman.d/mirrorlist&lt;/em&gt; and place geographically closest mirrors on top.&lt;/p&gt;

&lt;h2 id=&quot;base-group&quot;&gt;base group&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# base&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# pacstrap /mnt base base-devel&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# optional&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# pacstrap /mnt nano&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;This will install all packages from &lt;em&gt;base&lt;/em&gt; and &lt;em&gt;base-devel&lt;/em&gt; to the &lt;em&gt;root&lt;/em&gt; partition. Around 200 MiB packages will be downloaded and 700 MiB disk space consumed. Ignore the warning on &lt;em&gt;locale&lt;/em&gt; failure that will be handled after &lt;em&gt;chroot&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;base&lt;/em&gt; and &lt;em&gt;base-devl&lt;/em&gt; are &lt;em&gt;meta&lt;/em&gt; packages. Check &lt;a href=&quot;https://wiki.archlinux.org/index.php/Meta_package_and_package_group&quot;&gt;Meta package and package group&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;em&gt;base&lt;/em&gt; group does not even has a text editor. So we install &lt;em&gt;nano&lt;/em&gt; explicitly here. Other groups or individual packages can also be appended to the &lt;em&gt;pacstrap&lt;/em&gt; command. However, we&apos;d better install only necessary packages at this stage. Of course, we can install packages within &lt;a href=&quot;#chroot&quot;&gt;chroot&lt;/a&gt; by &lt;em&gt;pacman&lt;/em&gt; or when the OS is completely installed.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

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

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# genfstab -U /mnt &amp;gt;&amp;gt; /mnt/etc/fstab&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cat /mnt/etc/fstab&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-U&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-L&lt;/code&gt; use UUID and label respectively.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Attention that, the separate &lt;em&gt;cryptboot&lt;/em&gt; container is also included in &lt;em&gt;/etc/fstab&lt;/em&gt;. To support automount of &lt;em&gt;/boot&lt;/em&gt; partition after booting, we can resort to &lt;a href=&quot;https://wiki.archlinux.org/index.php/Dm-crypt/System_configuration#crypttab&quot;&gt;/mnt/etc/crypttab&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /mnt/etc/crypttab
cryptboot	/dev/sda2	/efi/arch-luks	cipher=aes-xts-plain64:sha512,size=512
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;copy-keyfile&quot;&gt;Copy Keyfile&lt;/h2&gt;

&lt;p&gt;Before chrooting, copy the key file to ESP partition.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cp ~/arch-luks.gpg /mnt/efi/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;chroot&quot;&gt;Chroot&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# arch-chroot /mnt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Much simpler than that of &lt;a href=&quot;https://www.zhstar.win/2015/09/10/lvm-luks-lvm/&quot;&gt;Gentoo&lt;/a&gt;. The shell prompt becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[root@archiso /#]&lt;/code&gt; and the default shell becomes Bash.&lt;/p&gt;

&lt;p&gt;To log all commands, set the following in &lt;em&gt;~/.bashrc&lt;/em&gt; empty string or negative integer:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ~/.bashrc
HISTSIZE=-1
HISTFILESIZE=-1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;time&quot;&gt;Time&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso /#] &lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sf&lt;/span&gt; /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

&lt;span class=&quot;c&quot;&gt;# On VirtualBox&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso /#] hwclock &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt;/--systohc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;localization&quot;&gt;Localization&lt;/h2&gt;

&lt;p&gt;Mainly, we will modify two files &lt;em&gt;/etc/locale.gen&lt;/em&gt; and &lt;em&gt;/etc/locale.conf&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Uncomment the following lines from &lt;em&gt;/etc/locale.gen&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;en_US.UTF-8 UTF-8
zh_CN.UTF-8 UTF-8
zh_CN.GB18030 GB18030
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Generate the locale:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] grep &apos;^[^#]&apos;/etc/locale.gen&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] locale-gen&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] locale -a&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] echo LANG=en_US.UTF-8 &amp;gt;&amp;gt; /etc/locale.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we set system-wide locale to &lt;em&gt;en_US.UTF-8&lt;/em&gt;. For per-user locale, leave it to &lt;em&gt;~/.config/locale.conf&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To set customized keymap permanently, edit (create) &lt;em&gt;/etc/vconsole.conf&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] echo &apos;KEYMAP=emacs&apos; &amp;gt;&amp;gt; /etc/vconsole.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check &lt;em&gt;/usr/share/keymaps/i386/qwerty&lt;/em&gt; for predefined keymaps. Switch to a keymap temporarily:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ &lt;span class=&quot;c&quot;&gt;# loadkeys emacs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attention, this only affects keyboard layout in virtual console. X keyboard layout is discuessed &lt;a href=&quot;/2019/03/11/x/#x-keyboard&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;network&quot;&gt;Network&lt;/h2&gt;

&lt;p&gt;Set hostname:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Create /etc/hostname&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] echo &quot;myhostname&quot; &amp;gt;&amp;gt; /etc/hostname&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Update &lt;em&gt;/etc/hosts&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;127.0.0.1	localhost
::1		localhost
127.0.1.1	myhostname.localdomain	myhostname
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The third line in the request uses &lt;em&gt;127.0.1.1&lt;/em&gt; instead of &lt;em&gt;127.0.0.1&lt;/em&gt;. It does not matter which one is used, actually. But &lt;a href=&quot;https://www.debian.org/doc/manuals/debian-reference/ch05.en.html#_the_hostname_resolution&quot;&gt;hostname resolution&lt;/a&gt; provide some information.&lt;/p&gt;

&lt;p&gt;Install NetworkManager:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] pacman -S networkmanager&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;NetworkManager has built-in DHCP client, so we don&apos;t need to install &lt;em&gt;dhcpcd&lt;/em&gt;. Aslo, it will pull in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant&lt;/code&gt;. To configure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant.conf&lt;/code&gt;, check &lt;a href=&quot;https://www.zhstar.win/2015/03/25/gentoo-installation/&quot;&gt;Gentoo Installation&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;initramfs-by-mkinitcpio&quot;&gt;Initramfs by mkinitcpio&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/mkinitcpio.conf
MODULES=(vfat)
HOOKS=(base udev autodetect modconf block filesystems keyboard fsck keymap encrypt lvm2)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;hook&lt;/th&gt;
      &lt;th&gt;info&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;keymap&lt;/td&gt;
      &lt;td&gt;needed as custom keymap (&lt;em&gt;emacs&lt;/em&gt;) is set in &lt;em&gt;vconsole.conf&lt;/em&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;encrypt&lt;/td&gt;
      &lt;td&gt;LUKS&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;lvm2&lt;/td&gt;
      &lt;td&gt;LVM&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;ol&gt;
  &lt;li&gt;Add &lt;strong&gt;vfat&lt;/strong&gt; module, otherwise &lt;em&gt;initramfs&lt;/em&gt; fails load the key file.&lt;/li&gt;
  &lt;li&gt;This is a &lt;em&gt;busybox&lt;/em&gt; based &lt;em&gt;initramfs&lt;/em&gt; configuration. It is different from &lt;em&gt;systemd init&lt;/em&gt; booting process, which is the next phase.&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkinitpico -H &amp;lt;hook-name&amp;gt;&lt;/code&gt; to check hooks info. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkinitcpio -L&lt;/code&gt; to list available hooks.&lt;/li&gt;
  &lt;li&gt;Remove &lt;em&gt;consolefont&lt;/em&gt; hook as it is unnecessary.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before creating the new &lt;em&gt;initramfs&lt;/em&gt;, we should install &lt;em&gt;lvm2&lt;/em&gt;, otherwise &lt;em&gt;mkinitcpio&lt;/em&gt; cannot find the hook:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] pacman -S lvm2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we will re-create the &lt;em&gt;initramfs&lt;/em&gt; to include the new hooks, though &lt;em&gt;pacstrap&lt;/em&gt; above already created it upon installation of &lt;em&gt;linux&lt;/em&gt; package (pulled in by the &lt;em&gt;base&lt;/em&gt; group).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] mkinitcpio -P&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;mkinitcpio&lt;/em&gt; will install generate two images, a &lt;em&gt;default&lt;/em&gt; and a &lt;em&gt;fallback&lt;/em&gt; that skips the autodetect hook thus including a full range of mostly-unneeded modules. Obviously, the fallback image is much bigger in size than the default one as it attempts to pull in as many modules as possible. Therefore, &lt;em&gt;fallback&lt;/em&gt; image generation usually reports &lt;a href=&quot;https://wiki.archlinux.org/index.php/Mkinitcpio#Possibly_missing_firmware_for_module_XXXX&quot;&gt;missing firmware&lt;/a&gt;. If the system does not have such hardware, it can be safely ignored. Otherwise, just install the relevant modules like &apos;wd719x-firmware&apos;.&lt;/p&gt;

&lt;h2 id=&quot;root-password&quot;&gt;root password&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] passwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;boot-loader---grub&quot;&gt;Boot loader - Grub&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] pacman -S grub efibootmgr intel-ucode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;efibootmgr&lt;/em&gt; is used by the GRUB installation script to write boot entries to NVRAM.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;intel-ucode&lt;/em&gt; is used to apply CPU stability and security updates during boot.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since the boot partition is encrypted by LUKS, so we should enable encryption option for Grub.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/default/grub
GRUB_ENABLE_CRYPTODISK=y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This option is used by &lt;em&gt;grub-install&lt;/em&gt; to generate &lt;em&gt;core.img&lt;/em&gt;. Then we set the kernel parameters so that &lt;em&gt;initramfs&lt;/em&gt; can unlock (using &lt;em&gt;encrypt&lt;/em&gt; hook) the encrypted swap, root, home partitions. For the arguments format, check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkinitcpio -H encrypt&lt;/code&gt; before editing &lt;em&gt;/etc/default/grub&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/default/grub

# or PARTUUID
GRUB_CMDLINE_LINUX=&quot;cryptdevice=UUID=of-sda4:cryptlvm cryptkey=UUID=of-sda2:auto:/arch-luks resume=UUID=of-volgrp-swap root=UUID=of-volgrp-root&quot;
# or /dev/mapper/volgrp-root
GRUB_CMDLINE_LINUX=&quot;cryptdevice=/dev/sda4:cryptlvm cryptkey=/dev/sda2:vfat:/arch-luks resume=/dev/volgrp/swap root=/dev/mapper/volgrp-root&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;It is error-prone to input UUID/PARTUUID without GUI, we can replace UUID with the device pathname.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Please make sure the key file is located under ESP partition.&lt;/p&gt;

    &lt;p&gt;If you forget the copy the key file before choorting, just exit the chroot, copy key file, and re-enter.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Kernel_parameters&quot;&gt;Kernel parameter&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;resume&lt;/em&gt; is used to &lt;em&gt;suspend to disk&lt;/em&gt;. &lt;em&gt;root&lt;/em&gt; is optional as long as &lt;em&gt;grub-mkconfig&lt;/em&gt; is used to generate the boot menu.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;mkinitpico&lt;/em&gt; by default, doe not support &lt;em&gt;gpg&lt;/em&gt; hook. Therefore, we cannot use a gpg-procted key file unless &lt;a href=&quot;https://aur.archlinux.org/packages/mkinitcpio-gnupg/&quot;&gt;mkinitcpio-gnupg&lt;/a&gt; is adopted. However, using a gpg-protected key file does not add security level compared to &lt;a href=&quot;#luks&quot;&gt;passphrase&lt;/a&gt; as the protected key file is also protected by passphrase. Hence, we use file &lt;em&gt;arch-luks&lt;/em&gt; directly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the configured, we can install the bootloader to ESP partition:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB --recheck --modules=&quot;part_gpt&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attention that, there is no &lt;em&gt;/dev/sda&lt;/em&gt; argument as that is for legacy BIOS booting.&lt;/p&gt;

&lt;p&gt;Then, generate boot menu:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] pacman -S os-prober&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] grub-mkconfig -o /boot/grub/grub.cfg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order for Grub to find Windows 10 system, please &lt;a href=&quot;https://wiki.archlinux.org/index.php/GRUB#Windows_8/10_not_found&quot;&gt;turn off Fast Startup&lt;/a&gt;. Also make sure &lt;a href=&quot;https://www.zhstar.win/2015/03/25/gentoo-installation/&quot;&gt;os-prober* is installed&lt;/a&gt;. By the way, &lt;em&gt;/boot&lt;/em&gt; and &lt;em&gt;/efi&lt;/em&gt; must also be mounted.&lt;/p&gt;

&lt;p&gt;If the &lt;em&gt;grub-mkconfig&lt;/em&gt; hangs there, probably read &lt;a href=&quot;https://bugs.archlinux.org/task/61040&quot;&gt;LVM need access to /run/lvm under new root&lt;/a&gt; and use the &lt;a href=&quot;https://bbs.archlinux.org/viewtopic.php?pid=1820949#p1820949&quot;&gt;suggested hack&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@archiso ~ # mkdir /mnt/hostlvm
root@archiso ~ # mount --bind /run/lvm /mnt/hostlvm
root@archiso ~ # arch-chroot /mnt
root@archiso ~ # ln -s /hostlvm /run/lvm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The following is for BIOS/GPT schema:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] pacman -S grub intel-ucode&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] grub-install --target=i386-pc /dev/sda&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] grub-mkconfig -o /boot/grub/grub.cfg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Although we install &lt;em&gt;x86_64&lt;/em&gt; Arch Linux, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--target&lt;/code&gt; should be &lt;em&gt;i386-pc&lt;/em&gt; due to BIOS booting scheme.&lt;/p&gt;

&lt;h2 id=&quot;reboot&quot;&gt;Reboot&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] cp .bash_history /path/to/usb-stick/bash.log (optionally as it remains after reboot but maybe overriden)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] exit/Ctrl-D&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# cp .zsh_history /path/to/usb-stick/zsh.log&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# umount -R /mnt&lt;/span&gt;
root@archiso ~ &lt;span class=&quot;c&quot;&gt;# reboot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We&apos;d better unmount all partitions under &lt;em&gt;/mnt&lt;/em&gt; to determine busy partitions and diagnose with &lt;em&gt;fuser&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;general-settings&quot;&gt;General Settings&lt;/h1&gt;

&lt;p&gt;Check &lt;a href=&quot;https://wiki.archlinux.org/index.php/General_recommendations&quot;&gt;Post-installation&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Enable NetworkManager&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# optional on desktop as networkmanager will detect Wi-Fi interface and ask for Wi-Fi password&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# wpa_passphrase ssid psk &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
   
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# systemctl &lt;span class=&quot;nb&quot;&gt;enable&lt;/span&gt;/start NetworkManager
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2015/03/25/gentoo-installation/&quot;&gt;New user account&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Swap file&lt;/p&gt;

    &lt;p&gt;Optional if swap partition is created.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# &lt;span class=&quot;nb&quot;&gt;dd &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1M &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1024 &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/zero &lt;span class=&quot;nv&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/swapfile
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# &lt;span class=&quot;nb&quot;&gt;chmod &lt;/span&gt;600 /swapfile
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# mkswap /swapfile
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# swapon /swapfile
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# swapon &lt;span class=&quot;nt&quot;&gt;--show&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# free &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Finally, addan entry to &lt;em&gt;/etc/fstab&lt;/em&gt;:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;/swapfile none swap defaults 0 0&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;ol&gt;
      &lt;li&gt;We must use the exact swap file path instead of UUID or Label.&lt;/li&gt;
      &lt;li&gt;To cease manual operation bother, try &lt;em&gt;systemd-swap&lt;/em&gt; that automates swap management.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;x&quot;&gt;X&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;/2019/03/11/x/&quot;&gt;X&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;time-1&quot;&gt;Time&lt;/h1&gt;

&lt;p&gt;Refer to &lt;a href=&quot;/2021/03/03/linux-time&quot;&gt;Linux Time&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;pacman&quot;&gt;pacman&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;/etc/pacman.conf&lt;/em&gt; sets almost everything regarding pacman, like database, cache, log, repos etc.&lt;/p&gt;

&lt;p&gt;pacman has two data warehouses:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;main repo. the synced database that stores package metadata (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pacman -S&lt;/code&gt;).&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-tzpvf&lt;/span&gt; /var/lib/pacman/sync/core.db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;local repo. the locally installed packages (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pacman -Q&lt;/code&gt;).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Ss regex                       # search for pkg&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Si pkg                         # show pkg info&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Sg grp                         # show group info&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -S pkg1 pkg2                    # install pkg1 and pkg2&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Sy archlinux-keyring           # upgrade keyring first&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Syu                            # roll the system&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Syu pkg                        # roll the system and install pgk&lt;/span&gt;
                                                       
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Qs pkg                         # search for locally installed pkg &lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Qi pkg                         # show locally installed pkg info&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Qe                             # list explicitly installed pkgs&lt;/span&gt;
                      
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pactree pkg                            # show dependency&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -F /path/to/file                # pathname in main repo&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Qo /path/to/file               # pathname in local repo&lt;/span&gt;
                                                       
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -D --asdeps pkg                 # mark a package as non-explicitly installed&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -D --asexplicit pkg             # mark a package as explicitly installed&lt;/span&gt;
                                                       
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -R pkg                          # remove pkg but leave dependencies alone&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -R grp&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Rs pkg                         # remove pkg and orphan dependencies; report error: argument &apos;-&apos; specified with empty stdin when no orphans&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Qtd                            # query orphaned packages&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Qtdq | pacman -Rns -           # remove orphaned packages&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] paccache -ruk0                         # clean downloaded packages&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] pacman -Scc                            # more aggressive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;aur&quot;&gt;AUR&lt;/h2&gt;

&lt;p&gt;Use &lt;a href=&quot;https://aur.archlinux.org/packages/wps-office-cn&quot;&gt;wps-office-cn&lt;/a&gt; as an example.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# get the PKGBUILD file&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;url.https://aur.archlinux.org/wps-office-cn.git.insteadOf=https://aur.archlinux.org/wps-office-cn.git&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
clone &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
https://aur.archlinux.org/wps-office-cn.git

&lt;span class=&quot;c&quot;&gt;# build the package&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;wps-office-cn&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;makepkg &lt;span class=&quot;nt&quot;&gt;-sirc&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# install the package&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-U&lt;/span&gt; wps-office-cn-11.1.0.11698-1-x86_64.pkg.tar.zst
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;wpspdf&lt;/em&gt; relies on &lt;a href=&quot;https://aur.archlinux.org/packages/libtiff5&quot;&gt;libtiff5&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To upgrade the package, repeat the above procedures.&lt;/p&gt;

&lt;h1 id=&quot;xterm&quot;&gt;Xterm&lt;/h1&gt;

&lt;p&gt;Install &lt;a href=&quot;https://wiki.archlinux.org/index.php/Xterm&quot;&gt;xterm&lt;/a&gt; package. Add the following into &lt;em&gt;~/.Xresources&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;XTerm.termName: xterm-256color
XTerm.vt100.locale: true
XTerm.vt100.metaSendsEscape: true
XTerm.vt100.reverseVideo: true

XTerm.vt100.backarrowKey: false
XTerm.ttyModes: erase ^?

XTerm.bellIsUrgent: true

XTerm.vt100.faceName: DejaVu Sans Mono:style=Book:antialias=true
XTerm.vt100.faceNameDoublesize: WenQuanYi WenQuanYi Bitmap Song
XTerm.vt100.faceSize: 10

XTerm.vt100.translations: #override \n\
    Ctrl Shift &amp;lt;Key&amp;gt;C: copy-selection(CLIPBOARD) \n\
    Ctrl Shift &amp;lt;Key&amp;gt;V: insert-selection(CLIPBOARD)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To take these settings into effect immediately:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] xrdb -merge ~/.Xresources&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] xrdb ~/.Xresources&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;xrdb&lt;/em&gt; without the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-merge&lt;/code&gt; option will reload &lt;em&gt;.Xresources&lt;/em&gt;, replacing current settings.&lt;/p&gt;

&lt;h2 id=&quot;copy-and-paste&quot;&gt;Copy and Paste&lt;/h2&gt;

&lt;p&gt;X11 has two kinds of buffers, namely PRIMARY and CLIPBOARD.&lt;/p&gt;

&lt;p&gt;To copy/paste to/from the CLIPBOARD , we select (highlight) text, press Ctrl-C and Ctrl-V. Selected text will be copied to PRIMARY buffer automatically. To paste from PRIMARY, press the middle mouse button. &lt;em&gt;Shift-insert&lt;/em&gt; also pastes from PRIMARY, but support only by terminal emulators. Implicitly, PRIMARY buffer lives a short period and will be replaced with new selection.&lt;/p&gt;

&lt;p&gt;Literally, we use &lt;em&gt;paste&lt;/em&gt; and &lt;em&gt;insert&lt;/em&gt;, &lt;em&gt;buffer&lt;/em&gt; and &lt;em&gt;selection&lt;/em&gt; interchangeably.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Buffer/Selection&lt;/th&gt;
      &lt;th&gt;In/Copy&lt;/th&gt;
      &lt;th&gt;Out/Paste/Insert&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;PRIMARY&lt;/td&gt;
      &lt;td&gt;select&lt;/td&gt;
      &lt;td&gt;MiddleMouse/Shift-Insert&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CLIPBOARD&lt;/td&gt;
      &lt;td&gt;select &amp;amp; Ctrl-C&lt;/td&gt;
      &lt;td&gt;Ctrl-V&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The actual buffer and key shortcut used are determined by X application. When it comes to Xterm, selection goes to PRIMARY by default. However, we can set selection to CLIPBOARD by Ctrl-MiddbleMouse and enable &lt;em&gt;Select to Clipboard&lt;/em&gt;. Alternatively, we can adjust &lt;em&gt;~/.Xresources&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ~/.Xresources
XTerm.vt100.selectToClipboard: true/false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Such settings will abandom the PRIMARY buffer. Instead, we add copy/paste shortcuts:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ~/.Xresources
XTerm.vt100.translations: #override \n\
    Ctrl Shift &amp;lt;Key&amp;gt;C: copy-selection(CLIPBOARD) \n\
    Ctrl Shift &amp;lt;Key&amp;gt;V: insert-selection(CLIPBOARD)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that each key binding line must be separated by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\n\&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;alacritty&quot;&gt;Alacritty&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;#xterm&quot;&gt;xterm&lt;/a&gt; is really outdated, use &lt;a href=&quot;https://wiki.archlinux.org/title/Alacritty&quot;&gt;Alacritty&lt;/a&gt; on Arch Linux.&lt;/p&gt;

&lt;p&gt;However, Alacritty sets ENV variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TERM&lt;/code&gt; to &lt;em&gt;alacritty&lt;/em&gt; which would &lt;a href=&quot;https://wiki.archlinux.org/title/Alacritty#Terminal_functionality_unavailable_in_remote_shells&quot;&gt;break&lt;/a&gt; remote shell (e.g. SSH) like below.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;WARNING: terminal is not fully functional
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For general compatibility, we can configure Alacritty and set ENV &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TERM&lt;/code&gt; to &lt;em&gt;xterm-256color&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /usr/share/doc/alacritty/example/alacritty.yml&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# /.config/alacritty/alacritty.yml&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;env&lt;/span&gt;:
  TERM: xterm-256color
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;resolution&quot;&gt;Resolution&lt;/h1&gt;

&lt;h2 id=&quot;virtual-terminal&quot;&gt;Virtual terminal&lt;/h2&gt;

&lt;p&gt;VirtualBox might fail to detect correct screen resolution for virtual terminal (console). Similar to &lt;a href=&quot;/2017/08/25/android-x86/&quot;&gt;Android-x86&lt;/a&gt; post, we should add custom kernel parameter through Grub bootloader.&lt;/p&gt;

&lt;p&gt;In Grub menu, press &lt;em&gt;e&lt;/em&gt;, and then &lt;em&gt;F2&lt;/em&gt;. You are now in command line prompt, type &lt;em&gt;vbeinfo&lt;/em&gt; to list possible resolutions. The one prefixed with &lt;em&gt;*&lt;/em&gt; is the default. Choose a desired one (i.e. 1366x768) and press &lt;em&gt;ESC&lt;/em&gt;. Append &lt;em&gt;video=1366x768&lt;/em&gt; to &lt;em&gt;linux&lt;/em&gt; line and press &lt;em&gt;F10&lt;/em&gt;. If none of the listed values meet requirement, we can try &lt;em&gt;vboxmanage setextradata&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage setextradata archlinux &lt;span class=&quot;s2&quot;&gt;&quot;CustomVideoMode1&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;1300x730x24&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The newly created value will be listed by &lt;em&gt;vbeinfo&lt;/em&gt;. To make the desired resolution permanent, we can edit &lt;em&gt;/etc/default/grub&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GRUB_CMDLINE_LINUX_DEFAULT=&quot;quiet video=1300x730&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can also set Grub&apos;s resolution by:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GRUB_GFXMODE=&quot;1366x768x24&quot; (for Grub menu itself)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Do not forget to update the Grub menu:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~ &lt;span class=&quot;c&quot;&gt;#] grub-mkconfig -o /boot/grub/grub.cfg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;xorg&quot;&gt;Xorg&lt;/h2&gt;

&lt;p&gt;Most of the time, Xorg resolution works out of box. Command line tool &lt;em&gt;xrandr&lt;/em&gt; and Xorg.conf can be used to set Xorg resolution.&lt;/p&gt;

&lt;p&gt;Query resolution:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@host ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;xrandr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The entry with star &lt;em&gt;*&lt;/em&gt; means current resolution while with &lt;em&gt;+&lt;/em&gt; means default preferred resolution. Set resolution:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@host ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$DISPLAY&lt;/span&gt;
user@host ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;xrandr &lt;span class=&quot;nt&quot;&gt;--display&lt;/span&gt; :0 &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; VGA-1 &lt;span class=&quot;nt&quot;&gt;--mode&lt;/span&gt; 1366x768
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can put the commands into &lt;em&gt;~/.xinitrc&lt;/em&gt; or &lt;em&gt;~/.config/awesome/autostart.sh&lt;/em&gt;. Alternatively, create Xorg.conf &lt;em&gt;/etc/X11/xorg.conf.d/10-resolution.conf&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Section &quot;Monitor&quot;
  Identifier &quot;VGA-1&quot;
  Modeline &quot;1368x768_60.00&quot;   85.25  1368 1440 1576 1784  768 771 781 798 -hsync +vsync
  Option &quot;PreferredMode&quot; &quot;1368x768_60.00&quot;
EndSection

Section &quot;Screen&quot;
  Identifier &quot;Screen 0&quot;
  Monitor &quot;VGA-1&quot;
  DefaultDepth 24
  SubSection &quot;Display&quot;
    Depth 24
  EndSubSection
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can get the Identifier value from &lt;em&gt;xrandr&lt;/em&gt; output.&lt;/p&gt;

&lt;h1 id=&quot;fcitx&quot;&gt;Fcitx&lt;/h1&gt;

&lt;p&gt;Check &lt;a href=&quot;/2015/03/25/gentoo-installation/&quot;&gt;Fcitx&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@host ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; fcitx-im fcitx-configtool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, append &lt;em&gt;run fcitx-autostart&lt;/em&gt; into &lt;em&gt;~/.config/awesome/autostart.sh&lt;/em&gt; and relaunch awesome.&lt;/p&gt;

&lt;p&gt;If some QT applications cannot input Chinese, ensure the following packages are available.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@host ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-Qi&lt;/span&gt; fcitx-qt5
user@host ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-Qi&lt;/span&gt; fcitx-qt6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;wps&quot;&gt;WPS&lt;/h1&gt;

&lt;p&gt;WPS on Linux has two version, namely &lt;em&gt;wps-office-cn&lt;/em&gt; and &lt;em&gt;wps-office&lt;/em&gt;. The CN version has much more features!&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://aur.archlinux.org/wps-office-cn.git
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;wps-office-cn
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;makepkg
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;pacman &lt;span class=&quot;nt&quot;&gt;-U&lt;/span&gt; wps-office-cn-11.1.0.10702-1-x86_64.pkg.tar.zst
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To display math symbols, we need to install &lt;a href=&quot;https://aur.archlinux.org/packages/ttf-wps-fonts/&quot;&gt;AUR ttf-wps-fonts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After closing WPS, the background process refuses to exit:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; /usr/lib/office6/wpsoffice
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; /usr/lib/office6/wpscloudsvr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, remove the excution permission may disallow WPS login. It&apos;s a trade-off.&lt;/p&gt;

&lt;h1 id=&quot;alsa&quot;&gt;ALSA&lt;/h1&gt;

&lt;p&gt;Assume the system has multiple audio cards, we may have adjust the default card.&lt;/p&gt;

&lt;p&gt;First, identify the card list.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;aplay &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /proc/asound/cards
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, update &lt;em&gt;~/.config/alsa/asoundrc&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;defaults.pcm.card 0
defaults.ctl.card 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Re-login and try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alsamixer&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;speaker-test&lt;/code&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>QQ robot</title>
   <link href="/2017/11/11/qqbot/"/>
   <updated>2017-11-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/11/11/qqbot</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Some APIs has beeb shut down and commands related to QQ number would fail!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/pandolia/qqbot&quot;&gt;QQBot&lt;/a&gt; written with Python, is a conversation robot base on Tencent&apos;s SmartQQ. This post describes QQbot on Gentoo PC.&lt;/p&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# within virtualenv&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;qqbot
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qqbot &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At the very first run, it may throw exception complaining lack of &lt;em&gt;sqlite3&lt;/em&gt; module. Make sure &lt;em&gt;python&lt;/em&gt; is built with relevant USE:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# echo &apos;dev-lang/python sqlite&apos; &amp;gt;&amp;gt; /etc/portage/package.use/python&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# emerge -av1 dev-lang/python:3.6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;startup&quot;&gt;Startup&lt;/h1&gt;

&lt;h2 id=&quot;help&quot;&gt;Help&lt;/h2&gt;

&lt;p&gt;Firstly, check basic parameters:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qqbot &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Especially, pay attention to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--daemon --bench --qq&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;first-run&quot;&gt;First run&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qqbot
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qqbot &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &amp;lt;qq number&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For the very first run, a QRcode pops up. Use QQ mobile app to scan for authorization. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-q&lt;/code&gt; attempts to load login cookies locally first and resorts to QRcode if that fails.&lt;/p&gt;

&lt;p&gt;In order that QRcode image pops up automatically, &lt;em&gt;gvfs-open&lt;/em&gt; or &lt;em&gt;shotwell&lt;/em&gt; must be available under Linux system, which should not be a problem as long as &lt;em&gt;gvfs&lt;/em&gt; package is installed. We can, however, manually open the QRcode located under &lt;em&gt;~/.qqbot-tmp/*.png&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Once login, a QQbot-term service is launched at port 8188 for interaction. Open a new terminal and:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq &lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq list &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; buddy | group | discuss &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq list buddy &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; name | nick | mark | qq &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; xxx
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq list buddy name:like:xxx
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq list group-member &amp;lt;qq group&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/assets/contact-attr-meannings.png&quot; alt=&quot;contact attributes&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For more operations, refer to official README.MD section 3.&lt;/p&gt;

&lt;p&gt;Aternatively, all operations can be done through HTTP API. For example, open &lt;em&gt;http://localhost:8188/list/buddy&lt;/em&gt;. We just separate each argument by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;. This is pretty useful when terminal output jumbers disorderly.&lt;/p&gt;

&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;/h1&gt;

&lt;p&gt;Check &lt;em&gt;~/.qqbot-tmp/v2.x.conf&lt;/em&gt;, and add a section for specific QQ account:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &quot;jim&quot; : {
        &quot;termServerPort&quot; : 8188,
        &quot;qq&quot; : &quot;123456789&quot;,
        &quot;daemon&quot; : True,
	&quot;plugins&quot; : [],
	&quot;pluginsConf&quot; : {},
    },
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;If there are multiple QQ accounts, please assign different &lt;em&gt;termServerPort&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;daemon&lt;/em&gt; mode releases terminal immediately after login. &lt;em&gt;stout&lt;/em&gt; and &lt;em&gt;stderr&lt;/em&gt; are redirected to &lt;em&gt;daemon-$qq.log&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;plugins&lt;/em&gt; list overides the default value.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With that configuration block, launch QQbot by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-u&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq stop
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qqbot &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; jim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;User configuration section name instead of QQ number after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-u&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;plugins&quot;&gt;Plugins&lt;/h1&gt;

&lt;p&gt;Pre-built plugins (i.e. &lt;em&gt;qqbot.plugins.sample&lt;/em&gt; ) are installed into &lt;em&gt;site-packages/qqbot/plugins&lt;/em&gt; reference to whom should be prefixed with &lt;em&gt;qqbot.plugins.&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To be simple, put personal plugin &lt;em&gt;myplugin.py&lt;/em&gt; under &lt;em&gt;~/.qqbot-tmp/plugins&lt;/em&gt; directory. You can load a plugin on-the-fly (hot-plug way) or by telling QQbot to load it on startup. Reference to personal plugin is the script filename.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;hot-plug method.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq plugins &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;list loaded&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq plug qqbot.plugins.test
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq plugins
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq unplug myplugin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Automatic plug&lt;/p&gt;

    &lt;p&gt;Put your desired plugin name to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;plugins&quot; : [&apos;autohello&apos;,]&lt;/code&gt; list.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;qqbotpluginsminiirc&quot;&gt;qqbot.plugins.miniirc&lt;/h1&gt;

&lt;p&gt;To be able to talk with IRC client:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;qq plug qqbot.plugins.miniirc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then launch Weechat:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/server add qqbot localhost/6667
# set qqbot nick; change sasl_mechanism to plain; turn off ssl and ssl_verify;
/connect qqbot
/list
/join #group
/query buddy-name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;minirrc&lt;/em&gt; plugin is limited and recognizes only QQ &lt;em&gt;name&lt;/em&gt;. For instance, you cannot &lt;em&gt;query&lt;/em&gt; a QQ number.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>V2</title>
   <link href="/2017/10/20/v2/"/>
   <updated>2017-10-20T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/10/20/v2</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#arch&quot; id=&quot;markdown-toc-arch&quot;&gt;Arch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#server-configuration&quot; id=&quot;markdown-toc-server-configuration&quot;&gt;Server Configuration&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#proxy-by-nginx-location&quot; id=&quot;markdown-toc-proxy-by-nginx-location&quot;&gt;Proxy by Nginx Location&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#proxy-by-http-header&quot; id=&quot;markdown-toc-proxy-by-http-header&quot;&gt;Proxy by HTTP Header&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#selinux-and-firewall&quot; id=&quot;markdown-toc-selinux-and-firewall&quot;&gt;SELinux and Firewall&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#verify-configuration&quot; id=&quot;markdown-toc-verify-configuration&quot;&gt;Verify Configuration&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#systemd&quot; id=&quot;markdown-toc-systemd&quot;&gt;Systemd&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#client-configuration&quot; id=&quot;markdown-toc-client-configuration&quot;&gt;Client Configuration&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#sniffing&quot; id=&quot;markdown-toc-sniffing&quot;&gt;sniffing&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#dns&quot; id=&quot;markdown-toc-dns&quot;&gt;DNS&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#domain-list&quot; id=&quot;markdown-toc-domain-list&quot;&gt;Domain List&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#cloudflare-cdn&quot; id=&quot;markdown-toc-cloudflare-cdn&quot;&gt;Cloudflare CDN&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#vmess-and-clock&quot; id=&quot;markdown-toc-vmess-and-clock&quot;&gt;Vmess and Clock&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#windows&quot; id=&quot;markdown-toc-windows&quot;&gt;Windows&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#global-proxy&quot; id=&quot;markdown-toc-global-proxy&quot;&gt;Global Proxy&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#macos&quot; id=&quot;markdown-toc-macos&quot;&gt;macOS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#refs&quot; id=&quot;markdown-toc-refs&quot;&gt;Refs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;arch&quot;&gt;Arch&lt;/h1&gt;

&lt;p&gt;The flowing table illustrates the network layers of a typical &lt;a href=&quot;https://www.v2fly.org&quot;&gt;V2&lt;/a&gt; deployment.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Firefox                                youtube.com
|                                      |
Socks V2 in                            Freedom V2 out
|                                      |
VMess V2 out                           VMess V2 in
|                                      |
Websocket V2 L6                        Websocket V2 L6
|                                      |
TLS V2 L5                              TCP V2 L5
|                                      |
HTTP =========== Cloudflare ========== HTTP Nginx proxy_pass
|                                      |
TLS                                    TLS
|                                      |
TCP                                    TCP
.                                      .
.                                      .
.                                      .
&amp;gt; .................................... &amp;lt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Encryption between Nginx and backend V2 can be abandoned (TCP V2 L5) as the traffic only circulates on local host.&lt;/li&gt;
  &lt;li&gt;Cloudflare now provides free websocket caching service. Therefore, we can turn on Cloudflare CDN to protect our V2 server. However, we cannot camouflage the Host header when Cloudflare CDN is turned on.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;p&gt;Download and extract &lt;a href=&quot;https://github.com/v2fly/v2ray-core/releases&quot;&gt;binary release&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# unzip /path/to/v2ray.zip -d /opt/v2ray/&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /opt/v2ray/log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As we will run the service as account &lt;em&gt;nobody&lt;/em&gt;, so make sure the directory and files onwership is correct.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# chown -R nobody: /opt/v2ray/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;server-configuration&quot;&gt;Server Configuration&lt;/h1&gt;

&lt;p&gt;V2 supports multiple configuration formats like Json, YAML, etc. By default, Json format is used. Specially, V2 Json allows comments (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;//foo&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/* bar */&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;proxy-by-nginx-location&quot;&gt;Proxy by Nginx Location&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;location /V2 {
    proxy_redirect off;
    proxy_pass http://127.0.0.1:10086;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection &quot;upgrade&quot;;
    proxy_set_header Host $http_host;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A side effect when browsing &apos;/V2&apos;, brwoser reports &quot;400 Bad Request&quot; as the backend V2 is a websocket server instead of a bare HTTP server. We may also receive &quot;502 Bad Gateway&quot; as the backend V2 is not started yet. We resolve the issue by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_intercept_errors&lt;/code&gt; as follows.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;proxy_intercept_errors on;
error_page 400 502 = /;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;error_page&lt;/code&gt; directive does &lt;em&gt;internal redirect&lt;/em&gt;. This method is always preferred. A more detailed method would be as below.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;proxy_intercept_errors on;

error_page 400 404 /404.html;
location = /404.html {
    internal;
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
    internal;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;internal&lt;/em&gt; directives specifies that a given location can only be used for internal redirects.&lt;/p&gt;

&lt;h2 id=&quot;proxy-by-http-header&quot;&gt;Proxy by HTTP Header&lt;/h2&gt;

&lt;p&gt;Unlike section &lt;a href=&quot;#nginx-template&quot;&gt;Proxy by Nginx Location&lt;/a&gt;, we can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy_pass&lt;/code&gt; based on customized HTTP headers under the &apos;/&apos; location, using the &lt;em&gt;if&lt;/em&gt; directive. This method requires V2 client to be 2.40.2 onwards.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssl_certificate      /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key  /etc/letsencrypt/live/www.example.com/privkey.pem;

location / {
    root /var/www;
  
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection &quot;upgrade&quot;;
    proxy_set_header Host $http_host;
  
    if ( $http_host = &quot;shit&quot; ) {
        proxy_pass http://127.0.0.1:10086;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The template above uses &apos;Host&apos; header to redirect requests to backend V2. The customized Host header &lt;strong&gt;must not&lt;/strong&gt; be the website domain. Otherwise, all normal HTTP traffic would go to V2. Usually, we set it to a public domain like &lt;em&gt;www.amazon.com&lt;/em&gt;. As you will, it can be any arbitrary strings, like &lt;em&gt;shit&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Modify &lt;a href=&quot;#client-configuration&quot;&gt;client configuration&lt;/a&gt; accordingly.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;wsSettings&quot;: {
  &quot;path&quot;: &quot;/&quot;,
  &quot;headers&quot;: {
    &quot;Host&quot;: &quot;shit&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Manually manipulate the &apos;Host&apos; header is not recommended as it is crucial for vhost matching. If V2 supports self-defined header, then it is far more desirable. By the way, it rerquires the &lt;a href=&quot;https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/&quot;&gt;evil if directive&lt;/a&gt;. Actually, we can also redirect based on the &apos;Upgrade&apos; header:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if ( $http_upgrade = &quot;websocket&quot; ) {
    proxy_pass http://127.0.0.1:10086;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This method still uses the evil &lt;em&gt;if&lt;/em&gt; directive.&lt;/p&gt;

&lt;h2 id=&quot;selinux-and-firewall&quot;&gt;SELinux and Firewall&lt;/h2&gt;

&lt;p&gt;On servers with &lt;a href=&quot;/2022/05/15/selinux/&quot;&gt;SELinux on&lt;/a&gt;, V2ray may report &lt;a href=&quot;https://github.com/v2ray/v2ray-core/issues/2451&quot;&gt;websocket: bad handshake&lt;/a&gt;. By default, SELinux &lt;a href=&quot;https://www.nginx.com/blog/using-nginx-plus-with-selinux/&quot;&gt;does not permit Nginx operations&lt;/a&gt;, such as proxying to upstream locations or &lt;a href=&quot;https://stackoverflow.com/q/27435655&quot;&gt;communicating with other processes through sockets&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check &lt;a href=&quot;/2022/05/15/selinux#audit-logs&quot;&gt;SELinux audit log&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# grep &apos;denied.*nginx&apos; /var/log/audit/audit.log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Turn SELinux bool value.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# getsebool -a | grep httpd_can_network_connect&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# setsebool -P httpd_can_network_connect 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Turn on V2 port if it is not &lt;a href=&quot;/2022/05/15/selinux#ports&quot;&gt;ephemeral ports&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# semanage port -l | grep [h]ttp_port_t&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# semanage port -a -t http_port_t -p tcp 10086&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, make sure the &lt;a href=&quot;/2021/07/18/aws/&quot;&gt;cloud instance&lt;/a&gt; allows at least 443 traffic.&lt;/p&gt;

&lt;h2 id=&quot;verify-configuration&quot;&gt;Verify Configuration&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# /opt/v2ray/v2ray test -c /opt/v2ray/config.json&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# sudo -u nobody -g nobody -- /opt/v2ray/v2ray -config /opt/v2ray/config.json&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# ss -nplt&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# tail -F /opt/v2ray/log/{access,error}.log&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# tail -F /var/log/nginx/{access,error}.log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;systemd&quot;&gt;Systemd&lt;/h2&gt;

&lt;p&gt;From now on, V2 provides built-in &lt;a href=&quot;/2021/07/19/systemd/&quot;&gt;Systemd&lt;/a&gt; unit file. V2 will run as &lt;em&gt;nobody&lt;/em&gt; instead of &lt;em&gt;root&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# systemctl daemon-reload&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# systemctl enable /opt/v2ray/systemd/v2ray.service&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl start v2ray.service&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable /opt/v2ray/systemd/v2ray@.service&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable v2ray@4.27.4&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl start v2ray@4.27.4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;client-configuration&quot;&gt;Client Configuration&lt;/h1&gt;

&lt;p&gt;As TLS encryption is adopted, extra Vmess encryption is unnecessary unless Cloudflare CDN is adopted. Details refer to &lt;a href=&quot;#cloudflare-cdn&quot;&gt;Cloudflare CDN&lt;/a&gt; section.&lt;/p&gt;

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

&lt;p&gt;This option is used by &lt;em&gt;inbound&lt;/em&gt; or &lt;em&gt;inbounddetour&lt;/em&gt; to retrieve domains upon receiving IP packets. Usually, users connect to a domain instead of an IP. Most of the time V2 &lt;em&gt;inbound&lt;/em&gt; or &lt;em&gt;inbounddetour&lt;/em&gt; receives the domain (as DNS query first) such that relevant traffic is directed in accord with &lt;em&gt;domain&lt;/em&gt; rules of the &lt;em&gt;routing&lt;/em&gt; section.&lt;/p&gt;

&lt;p&gt;However, it happens that a client may connect to an IP directly (i.e. Telegram). What is worse, IP packets can bypass &lt;em&gt;domain&lt;/em&gt; rules.&lt;/p&gt;

&lt;p&gt;Additionally, if a user forgets to select:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Proxy DNS when using SOCKS v5&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;in Firefox setting, DNS queries would be sent to local DNS service and then IP packets go to V2. Obviously, local DNS replies are usually poisoned.&lt;/p&gt;

&lt;p&gt;Therefore, &lt;em&gt;sniffing&lt;/em&gt; comes to help such that it siniffs domains from IP packets, reset the connection, and route against &lt;em&gt;domain&lt;/em&gt; rules. DNS poision issue is resolved as well.&lt;/p&gt;

&lt;p&gt;From the discussion, we find &lt;em&gt;routing&lt;/em&gt; based on IP packet sniffing is more reliable and robust. In the meantime, &lt;em&gt;dokodemo&lt;/em&gt; transparent proxy redirects IP packets based on Iptables.&lt;/p&gt;

&lt;h2 id=&quot;dns&quot;&gt;DNS&lt;/h2&gt;

&lt;p&gt;V2 has built-in DNS support, mainly for two purposes:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Support the &lt;em&gt;routing&lt;/em&gt; rules based on &lt;em&gt;domainStrategy&lt;/em&gt; setting.&lt;/p&gt;

    &lt;p&gt;For example, in order to match an IP rule in &lt;em&gt;routing&lt;/em&gt;, the target domain must be resolved to IP first by the &lt;em&gt;dns&lt;/em&gt; section. That IP will &lt;strong&gt;only&lt;/strong&gt; be used to re-reroute the request, namely deciding which &lt;em&gt;outbound&lt;/em&gt; to use!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;DNS service for the &lt;em&gt;freedom&lt;/em&gt; outbound.&lt;/p&gt;

    &lt;p&gt;When a target domain is routed to the &lt;em&gt;freedom&lt;/em&gt; outbound, it should be &lt;em&gt;directly&lt;/em&gt; accessed. V2ray will consult the &lt;em&gt;dns&lt;/em&gt; section to resolve the domain. Once got the host IP to connect to, it should be routed again in the &lt;em&gt;routing&lt;/em&gt; section. This is a little bit confusing!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Apart from the the built-in DNS support, V2ray has a &lt;em&gt;dns&lt;/em&gt; outbound that can be used to serve as a open DNS service, similar to Dnsmasq.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Disable &quot;Proxy DNS when using SOCKS v5&quot; in Firefox.&lt;/li&gt;
  &lt;li&gt;At V2ray client side:
    &lt;ol&gt;
      &lt;li&gt;Set up a &lt;em&gt;dokodemo-door&lt;/em&gt; inbound at port 53, receiving DNS query.&lt;/li&gt;
      &lt;li&gt;Set up a &lt;em&gt;dns&lt;/em&gt; outbound.&lt;/li&gt;
      &lt;li&gt;Set up a &lt;em&gt;routing&lt;/em&gt; rule, routes the query from &lt;em&gt;dokodemo-door&lt;/em&gt; inbound to the &lt;em&gt;dns&lt;/em&gt; outbound.&lt;/li&gt;
      &lt;li&gt;The &lt;em&gt;dns&lt;/em&gt; outound intercept DNS queries and redirect the queries to the &lt;em&gt;dns&lt;/em&gt; section.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We cal also combine V2ray and Dnsmasq. Queries are first sent to local Dnsmasq, then to V2ray &lt;em&gt;dokodemo-door&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;domain-list&quot;&gt;Domain List&lt;/h2&gt;

&lt;p&gt;V2ray has built-in domain list, like &lt;em&gt;geosite.dat&lt;/em&gt; and &lt;em&gt;geoip.dat&lt;/em&gt;, which can be used in the &lt;em&gt;routing&lt;/em&gt; section and the &lt;em&gt;dns&lt;/em&gt; section to achieve &lt;em&gt;smart&lt;/em&gt; proxy.&lt;/p&gt;

&lt;p&gt;An enhanced version can be found at &lt;a href=&quot;https://github.com/Loyalsoldier/v2ray-rules-dat&quot;&gt;v2ray-rules-dat&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Besides, V2ray can also load domain list from external files with prefix &lt;em&gt;ext&lt;/em&gt;, like &lt;a href=&quot;https://github.com/ToutyRater/V2Ray-SiteDAT&quot;&gt;h2y.dat&lt;/a&gt;. Similar to the built-in domain list, reference to external list can be:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;ext:h2y.dat:ad&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;cloudflare-cdn&quot;&gt;Cloudflare CDN&lt;/h2&gt;

&lt;p&gt;Turn on CDN to hide server IP from censorship and probably accelerate speed.&lt;/p&gt;

&lt;p&gt;Cloudflare supports caching &lt;em&gt;websocket&lt;/em&gt; traffic for free accounts. To enable Cloudflare CDN on V2, just click the orange symbol on DNS record.&lt;/p&gt;

&lt;p&gt;You might wait for a while before the DNS setting comes into effect. Check by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dig your.domain.com&lt;/code&gt; and find the returned IP be that of Cloudflare&apos;s CDN servers.&lt;/p&gt;

&lt;p&gt;A few notes:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Cloudflare&apos;s free CDN service actually &lt;em&gt;degrade&lt;/em&gt; instead of &lt;em&gt;accelerate&lt;/em&gt; your service.&lt;/p&gt;

    &lt;p&gt;This can be caused by ISP dropping IP packets to its servers. What&apos;s worse, Cloudflare may do this on purpose for paid service.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Once enabled, we &lt;strong&gt;must&lt;/strong&gt; reset &lt;a href=&quot;#proxy-by-http-header&quot;&gt;Customized HTTP header&lt;/a&gt; to the real domain name instead of &lt;em&gt;shit&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Otherwise, V2 client cannot establish TLS session with Cloudflare as CDN servers does not have a &lt;em&gt;shit&lt;/em&gt; vhost.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;VMess encryption &lt;strong&gt;must&lt;/strong&gt; be enabled besides TLS, thus Cloudflare cannot see VMess payload.&lt;/p&gt;

    &lt;p&gt;You&apos;d better not use V2 do confidential communication such as Email, Login etc.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;vmess-and-clock&quot;&gt;Vmess and Clock&lt;/h2&gt;

&lt;p&gt;Vmess depends on system clock to do authorization, so make sure the clock delta between client and server fall within 90s.&lt;/p&gt;

&lt;h1 id=&quot;windows&quot;&gt;Windows&lt;/h1&gt;

&lt;h2 id=&quot;global-proxy&quot;&gt;Global Proxy&lt;/h2&gt;

&lt;p&gt;To enable global Socks proxy on Windows, the address part in &quot;Windows Settings&quot; should be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://socks=127.0.0.1&lt;/code&gt;. Alternatively and &lt;em&gt;recommended&lt;/em&gt;, use the &quot;Internet Options&quot;, &quot;Connections&quot;, &quot;LAN settings&quot;, &quot;Proxy Server&quot;, &quot;Advanced&quot; and &quot;Bypass proxy server for local addresses&quot;.&lt;/p&gt;

&lt;p&gt;Alternatively, use 3rd-party tools like &lt;a href=&quot;https://github.com/Dreamacro/clash&quot;&gt;Clash&lt;/a&gt; as the client side of V2. Whatever methods you choose, make sure to bypass the remote domain and VPS IP.&lt;/p&gt;

&lt;p&gt;However, Windows UWP app like Mail, Calendar etc. have their own sandbox (namely App Container) and &lt;a href=&quot;https://zhuanlan.zhihu.com/p/29989157&quot;&gt;does not respect system proxy&lt;/a&gt;, including the &quot;Microsoft Store&quot; itself. The container prevents App from connecting to system&apos;s &lt;em&gt;loopback&lt;/em&gt; interface, such that Wireshark cannot capture UWP traffic and UWP does not use global proxy. Clash supports UWP loopback access and enjoys the proxy.&lt;/p&gt;

&lt;p&gt;It is recommended to use Windows&apos; built-in &lt;em&gt;CheckNetIsolation.exe&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PS C:\Users\jim&amp;gt; CheckNetIsolation.exe -?
PS C:\Users\jim&amp;gt; CheckNetIsolation.exe LoopbackExempt -?
PS C:\Users\jim&amp;gt; CheckNetIsolation.exe LoopbackExempt -s

PS C:\Users\jim&amp;gt; CheckNetIsolation.exe LoopbackExempt -a -n=&amp;lt;package-family-name&amp;gt;
PS C:\Users\jim&amp;gt; CheckNetIsolation.exe LoopbackExempt -a -p=&amp;lt;sid&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;How to find out an App&apos;s &quot;Package Family Name&quot;?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PS C:\Users\jim&amp;gt; Get-AppxPackage &amp;gt; lst  # list full list
PS C:\Users\jim&amp;gt; Get-Content .\lst.md | Select-String -Pattern &quot;wechat&quot;
PS C:\Users\jim&amp;gt; Get-Content .\lst.md | Select-String -Pattern &quot;.*windowscommunicationsapps.*&quot;  # Mail and Calender
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;macos&quot;&gt;macOS&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://v2raya.org&quot;&gt;V2raya&lt;/a&gt; deployed by &lt;a href=&quot;/2020/10/12/macos/#homebrew&quot;&gt;Homebrew&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Originally, V2raya depends on V2ray, so we should install &quot;v2ray&quot; first. However, V2raya now automatically installs the dependency &quot;v2ray5&quot; (version 5).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# install v2ray (deprecated)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;v2ray

&lt;span class=&quot;c&quot;&gt;# install v2raya (automatically pulls V2ray5)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew tap v2raya/v2raya
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;v2raya/v2raya/v2raya

&lt;span class=&quot;c&quot;&gt;# install homebrew-services&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew services list

&lt;span class=&quot;c&quot;&gt;# start v2raya&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew services start v2raya
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew services info v2raya
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Go to &lt;a href=&quot;http://localhost:2017&quot;&gt;http://localhost:2017&lt;/a&gt; for setup. For example, update &lt;a href=&quot;https://github.com/Loyalsoldier/v2ray-rules-dat&quot;&gt;geoip.dat and geosite.dat&lt;/a&gt; at &quot;/opt/homebrew/Cellar/v2ray/4.45.2/share/v2ray&quot;. Then, go to &quot;V2raya - Settings - Traffic Splitting Mode of Rule Port - Routing A - Configure&quot;, append the following line:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;domain(geosite:category-ads-all) -&amp;gt; block
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The resulted V2 config is located at &lt;em&gt;~/.config/v2raya/config.json&lt;/em&gt;. We can add any routing rules on demand.&lt;/p&gt;

&lt;p&gt;Currently, V2raya on macOS does not support transparent proxy. We can set macOS system proxy to use V2raya. Attention please; since &lt;a href=&quot;https://v2raya.org/docs/manual/routinga/&quot;&gt;RoutingA (Advanced)&lt;/a&gt; is used, the Socks and Http inbound port are 20173 and 20172 respectively.&lt;/p&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://guide.v2fly.org/&quot;&gt;Bai hua wen&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.igfw.net/archives/13463&quot;&gt;V2Ray的Websocket模式使用CDN加速并隐藏VPS真实IP&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Let's Encrypt</title>
   <link href="/2017/10/10/lets-encrypt/"/>
   <updated>2017-10-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/10/10/lets-encrypt</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#acme-and-certbot&quot; id=&quot;markdown-toc-acme-and-certbot&quot;&gt;ACME and Certbot&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#certbot-configuration&quot; id=&quot;markdown-toc-certbot-configuration&quot;&gt;Certbot Configuration&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#nginx-template&quot; id=&quot;markdown-toc-nginx-template&quot;&gt;Nginx Template&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#obtain-a-certificate&quot; id=&quot;markdown-toc-obtain-a-certificate&quot;&gt;Obtain a Certificate&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#webroot-authenticator&quot; id=&quot;markdown-toc-webroot-authenticator&quot;&gt;Webroot Authenticator&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#standalone-authenticator&quot; id=&quot;markdown-toc-standalone-authenticator&quot;&gt;Standalone Authenticator&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#dns-authenticator-for-wildcard-certificate&quot; id=&quot;markdown-toc-dns-authenticator-for-wildcard-certificate&quot;&gt;DNS Authenticator for Wildcard Certificate&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#manage-a-certificate&quot; id=&quot;markdown-toc-manage-a-certificate&quot;&gt;Manage a Certificate&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#change-a-certificates-domains&quot; id=&quot;markdown-toc-change-a-certificates-domains&quot;&gt;Change a Certificate&apos;s Domains&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#renew-a-certificate&quot; id=&quot;markdown-toc-renew-a-certificate&quot;&gt;Renew a Certificate&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#manual-renewal&quot; id=&quot;markdown-toc-manual-renewal&quot;&gt;Manual Renewal&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#automatic-renwal&quot; id=&quot;markdown-toc-automatic-renwal&quot;&gt;Automatic Renwal&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#backup-the-account-and-certificates&quot; id=&quot;markdown-toc-backup-the-account-and-certificates&quot;&gt;Backup the Account and Certificates&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#share-certificates&quot; id=&quot;markdown-toc-share-certificates&quot;&gt;Share Certificates&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#deploy-certificates&quot; id=&quot;markdown-toc-deploy-certificates&quot;&gt;Deploy Certificates&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ecdsa-certificate-and-rsa-certificate&quot; id=&quot;markdown-toc-ecdsa-certificate-and-rsa-certificate&quot;&gt;ECDSA Certificate and RSA Certificate&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;acme-and-certbot&quot;&gt;&lt;a href=&quot;https://www.linuxbabe.com/security/letsencrypt-webroot-tls-certificate&quot;&gt;ACME and Certbot&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;In order to manage &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;Let&apos;s Encrypt&lt;/a&gt; certificates, we need a client tool that supports the &lt;a href=&quot;https://tools.ietf.org/html/rfc8555&quot;&gt;RFC 8555 Automated Certificate Management Environm (ACME) protocol&lt;/a&gt;. ACME clients communicate with servers of Let&apos;s Encrypt using ACME protocol, to automate the following jobs:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Generate key pair.&lt;/li&gt;
  &lt;li&gt;Create and send Certificate Signing Request (CSR).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://support.sectigo.com/Com_KnowledgeDetailPageFaq?Id=kA01N000000brbt&quot;&gt;Domain Control Validation (DCV)&lt;/a&gt;. &lt;a href=&quot;https://docs.digicert.com/manage-certificates/organization-domain-management/managing-domains-cc-guide/domain-pre-validation-domain-control-validation/&quot;&gt;Challenge ownership&lt;/a&gt; of domain or web server.&lt;/li&gt;
  &lt;li&gt;Automatically renew certificates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let&apos;s Encrypt officially recommends the &lt;a href=&quot;https://certbot.eff.org/docs/using.html&quot;&gt;Certbot&lt;/a&gt; client.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# dnf --enablerepo ol8_developer_EPEL search certbot&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# dnf --enablerepo ol8_developer_EPEL install certbot&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# dnf repoquery -l certbot&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# certbot -h all&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# certbot certificates # List existing certificates&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To run &lt;em&gt;certbot&lt;/em&gt;, we supply a subcommand like &lt;em&gt;certonly&lt;/em&gt; (obtain a certificate), &lt;em&gt;install&lt;/em&gt; (update vhost), &lt;em&gt;run&lt;/em&gt; (both) etc. Whenever possible, try with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dry-run&lt;/code&gt; first.&lt;/p&gt;

&lt;p&gt;If no subcommand is given, then &lt;em&gt;run&lt;/em&gt; is assumed. A subcommand accepts different types of plugins, namely &lt;em&gt;authenticator&lt;/em&gt; plugins and &lt;em&gt;installer&lt;/em&gt; plugins. The general usage looks like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;certbot subcommand --plugin-name ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;certonly&lt;/em&gt; subcommand and &lt;em&gt;install&lt;/em&gt; subcommand accept &lt;em&gt;authenticator&lt;/em&gt; plugins and &lt;em&gt;installer&lt;/em&gt; plugins respectivelly, while the &lt;em&gt;run&lt;/em&gt; subcommand accepts plugins belonging to both types.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;authenticator&lt;/em&gt; plugins challenge you whether you are eligible for a certificate by verifying the domain owership. &lt;em&gt;installer&lt;/em&gt; plugins automatically modify web server&apos;s configuration with specified certificate. Most of the time, we firstly use &lt;em&gt;authenticator&lt;/em&gt; plugins to obtain a certificate and then &lt;em&gt;manually&lt;/em&gt; update configurations of the web server. We don&apos;t use &lt;em&gt;installer&lt;/em&gt; plugins/&lt;/p&gt;

&lt;p&gt;Examples of &lt;em&gt;authenticator&lt;/em&gt; plugins are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--webroot&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--standalone&lt;/code&gt;. There does not exist plugins exclusively belonging to the &lt;em&gt;installer&lt;/em&gt; type. However, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--apache&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--nginx&lt;/code&gt; belong to both types of &lt;em&gt;authenticator&lt;/em&gt; and &lt;em&gt;installer&lt;/em&gt;, and can be used with the &lt;em&gt;run&lt;/em&gt; subcommand to both obtain and install a certificate.&lt;/p&gt;

&lt;p&gt;The following table simply presents their relationship:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;subcommand&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;type&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;plugin&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;certonly&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;authenticator&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;webroot, standalone, dns-cloudflare&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;install&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;installer&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;n/a&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;run (default)&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;both&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;apache, nginx&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;certbot-configuration&quot;&gt;Certbot Configuration&lt;/h2&gt;

&lt;p&gt;By default, the configuration is:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/letsencrypt/cli.ini
preconfigured-renewal &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; True
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A few custom configs:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/letsencrypt/cli.ini

# TOS
agree-tos = true

# cert notification
email = alice@example.com

# ECC key by default
key-type = ecdsa
elliptic-curve = secp384r1

# RSA key size
rsa-key-size = 4096

# renewal hook
deploy-hook = systemctl reload nginx.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;nginx-template&quot;&gt;Nginx Template&lt;/h1&gt;

&lt;p&gt;A simple Nginx HTTP template.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;server {
	listen       80 default_server;
	listen       [::]:80 default_server;
	server_name  _;
	root         /usr/share/nginx/html;

	# Load configuration files for the default server block.
	include /etc/nginx/default.d/*.conf;

	location / {
	}

	error_page 404 /404.html;
		location = /40x.html {
	}

	error_page 500 502 503 504 /50x.html;
		location = /50x.html {
	}
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;obtain-a-certificate&quot;&gt;Obtain a Certificate&lt;/h1&gt;

&lt;p&gt;ACME challenge is a complex process, you&apos;d better turn off CDN caching before applying for a certificate.&lt;/p&gt;

&lt;h2 id=&quot;webroot-authenticator&quot;&gt;Webroot Authenticator&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# certbot -h certonly&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# certbot -h webroot&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# certbot certonly --webroot -w /var/www/example.com -d example.com,www.example.com -w /var/www/b.example.com -d b1.example.com -d b2.example.com --email &quot;name@example.com&quot; --dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As the name implies, &lt;em&gt;certonly&lt;/em&gt; only obtains certificates but does not install them. When requesting a certificate for multiple domains, each domain will use the most recently specified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--webroot-path, -w&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--email&lt;/code&gt; option is to receive notification like expiration message. Multiple domain names can be separated by comma in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d&lt;/code&gt; argument or by individual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d&lt;/code&gt; arguments. Always append the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dry-run&lt;/code&gt; before any real operation.&lt;/p&gt;

&lt;p&gt;Use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--webroot&lt;/code&gt; authenticator if you have full control over the &lt;em&gt;running&lt;/em&gt; web server and the domain. Let&apos;s Encrypt&apos;s ACME server tells the Certbot client to write &lt;em&gt;unique&lt;/em&gt; files under the root of your web server (i.e. &lt;em&gt;/usr/share/nginx/html/&lt;/em&gt;). This step is challenging you whether you do own the web server (i.e. write access). The file URL takes the form:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://domain/.well-known/acme-challenge/&amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Afterwards, the ACME server tries to fetch the URL, verifying you own the domain. Therefore, make sure the domain name is finally resolved to the web server IP and the web server is running on HTTP 80 (NOT HTTPS 443). Though, the &lt;em&gt;webroot&lt;/em&gt; authenticator use HTTP to challenge the ownership, the security of Certbot itself is guranteed by ACME protocol. We call this kind of challenge &lt;em&gt;http-01&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You can cover your web server with CDN (i.e. Cloudflare), as the challenge method is to download the unique file. However, if the CDN enables HSTS, then temporarily turn it off by removing the caching capability in DNS settting.&lt;/p&gt;

&lt;p&gt;Once downloaded, the ACME server also compares the file hashes of the fetched copy with its local store.&lt;/p&gt;

&lt;h2 id=&quot;standalone-authenticator&quot;&gt;Standalone Authenticator&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--standalone&lt;/code&gt; authenticator is usually used when the host where you run &lt;em&gt;certbot&lt;/em&gt; is not the one you would like to host your web server.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# certbot -h standalone&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# certbot certonly --standalone -d www.example.com,blog.example.com --dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It starts a &lt;em&gt;temporary standalone web server&lt;/em&gt; to talk to Let’s Encrypt. Therefore, it does not verify web server. You must make sure &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.2&quot;&gt;port 80&lt;/a&gt; is available. You may have to turn down existing web servers to release port 80.&lt;/p&gt;

&lt;p&gt;Recall that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--webroot&lt;/code&gt; challenge domain onwership by &lt;em&gt;http-01&lt;/em&gt;, GETting an unique URL. Then how does &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--standalone&lt;/code&gt; challenge the domain onwership? By &lt;em&gt;http-01&lt;/em&gt; too!&lt;/p&gt;

&lt;p&gt;Though ACME protocol supports challenge with &lt;a href=&quot;https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.3&quot;&gt;tls-01&lt;/a&gt; by verifying the &lt;em&gt;temporarily&lt;/em&gt; self-generated certificate, but Certbot only implements HTTP 80. If you have chosen to use &lt;em&gt;tls-o1&lt;/em&gt;, then you must make sure the domain name is &lt;em&gt;directly&lt;/em&gt; resolved to the host IP where you apply for certificates &lt;em&gt;certbot&lt;/em&gt; client. If the domain name is resolved to the host IP, it means you manage the domain. You cannot cover your domain with CDN, otherwise the ACME server would got the CDN&apos;s certificate instead of the temporary one by Certbot.&lt;/p&gt;

&lt;h2 id=&quot;dns-authenticator-for-wildcard-certificate&quot;&gt;DNS Authenticator for Wildcard Certificate&lt;/h2&gt;

&lt;p&gt;With the &lt;em&gt;certbot&lt;/em&gt; client, the only way to obtain a wildcard certificate from Let&apos;s Encrypt is using DNS Plugins. DNS plugins belong to the &lt;em&gt;authenticator&lt;/em&gt; type but challenge you by DNS protocol.&lt;/p&gt;

&lt;p&gt;Basically, a DNS plugin uses a API token from the DNS platform to first add a TXT record and then remove that record, such that you are proved to own the domain name. Therefore, the DNS authenticator does not interfere in web server.&lt;/p&gt;

&lt;p&gt;For each DNS platform, &lt;em&gt;certbot&lt;/em&gt; provodes a corresponding DNS plugin. DNS plugins are not installed by default.&lt;/p&gt;

&lt;p&gt;Take &lt;a href=&quot;https://certbot-dns-cloudflare.readthedocs.io/en/stable/&quot;&gt;Cloudflare&lt;/a&gt; for example. Firstly, let&apos;s install DNS plugin:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nt&quot;&gt;--enablerepo&lt;/span&gt; ol8_developer_EPEL &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;python3-certbot-dns-cloudflare
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then create API token for the DNS plugin at &lt;a href=&quot;https://dash.cloudflare.com/?to=/:account/profile/api-tokens&quot;&gt;API Token&lt;/a&gt;. Please configure the IP whitelist. We test the token:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-X&lt;/span&gt; GET &lt;span class=&quot;s2&quot;&gt;&quot;https://api.cloudflare.com/client/v4/user/tokens/verify&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;      &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Authorization: Bearer xxxxxxxxxxxxxyyyyyyyyyyyyyzzzzzzzzzzzzz&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;      &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type:application/json&quot;&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-X&lt;/span&gt; GET &lt;span class=&quot;s2&quot;&gt;&quot;https://api.cloudflare.com/client/v4/zones/&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;      &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Authorization: Bearer xxxxxxxxxxxxxyyyyyyyyyyyyyzzzzzzzzzzzzz&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;      &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Content-Type:application/json&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The token is used for both cert creation and renewal. Store the token somewhere:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p ~/root/.secrets/certbot&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# chmod 700 ~/root/.secrets/certbot&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# cat &amp;gt; /root/.secrets/certbot/cloudflare.ini &amp;lt;&amp;lt;EOF&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# Cloudflare API token used by Certbot&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; dns_cloudflare_api_token &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; xxxxxxxxxxxxxyyyyyyyyyyyyyzzzzzzzzzzzzz
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; EOF

~ &lt;span class=&quot;c&quot;&gt;# chmod 600 /root/.secrets/certbot/cloudflare.ini&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally create wildcard certificate:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# certbot certonly --dry-run \&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--dns-cloudflare&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--dns-cloudflare-credentials&lt;/span&gt; /root/.secrets/certbot/cloudflare.ini &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--dns-cloudflare-propagation-seconds&lt;/span&gt; 60 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--domains&lt;/span&gt; example.com,&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--cert-name&lt;/span&gt; example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--key-type&lt;/span&gt; ecdsa &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;--elliptic-curve&lt;/span&gt; secp384r1 &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;manage-a-certificate&quot;&gt;Manage a Certificate&lt;/h1&gt;

&lt;p&gt;No matter which plugins you use, the generated certificates are placed under &lt;em&gt;/etc/letsencrypt/&lt;/em&gt;. Also the arguments used to generate the certificates are stored alongside for &lt;a href=&quot;#renew-a-certificate&quot;&gt;latter renwal&lt;/a&gt;. The directory tree looks like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# tree /etc/letsencrypt/
/etc/letsencrypt/
├── accounts
│   ├── acme-staging-v02.api.letsencrypt.org
│   │   └── directory
│   │       └── 74cfecb0fe45ec846ae6cc76b6ba0b44
│   │           ├── meta.json
│   │           ├── private_key.json
│   │           └── regr.json
│   └── acme-v02.api.letsencrypt.org
│       └── directory
│           └── 34ec5a2656cb495bb9c7b74755d5dfad
│               ├── meta.json
│               ├── private_key.json
│               └── regr.json
├── archive
│   └── example.com
│       ├── cert1.pem
│       ├── chain1.pem
│       ├── fullchain1.pem
│       └── privkey1.pem
├── cli.ini
├── csr
│   └── 0000_csr-certbot.pem
├── keys
│   └── 0000_key-certbot.pem
├── live
│   ├── README
│   └── example.com
│       ├── cert.pem -&amp;gt; ../../archive/example.com/cert1.pem
│       ├── chain.pem -&amp;gt; ../../archive/example.com/chain1.pem
│       ├── fullchain.pem -&amp;gt; ../../archive/example.com/fullchain1.pem
│       ├── privkey.pem -&amp;gt; ../../archive/example.com/privkey1.pem
│       └── README
├── renewal
│   └── example.com.conf
└── renewal-hooks
    ├── deploy
    ├── post
    └── pre

18 directories, 20 files
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You will find a certificate has different version, namely &lt;em&gt;fullchain.pem&lt;/em&gt;, &lt;em&gt;chain.pem&lt;/em&gt; and &lt;em&gt;cert.pem&lt;/em&gt;. Use &lt;em&gt;fullchain.pem&lt;/em&gt; &lt;a href=&quot;https://github.com/v2ray/v2ray-core/issues/509#issuecomment-319321002&quot;&gt;whenever possible&lt;/a&gt; as it is a combination of &lt;em&gt;chain.pem&lt;/em&gt; and &lt;em&gt;cert.pem&lt;/em&gt;. Use &lt;em&gt;chain.pem&lt;/em&gt; for OCSP stapling as that does not require the leaf cert.&lt;/p&gt;

&lt;p&gt;First, list existing certificates:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# certbot certificates&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# certbot certificates --cert-name example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It&apos;s not unusual that different certificates share common FQDNs. From the output, you will find each certificate has a name. By default, it&apos;s named afer the first FQDN from option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--domains&lt;/code&gt;. We can explicitly set a certificate name with option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cert-name&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;change-a-certificates-domains&quot;&gt;Change a Certificate&apos;s Domains&lt;/h2&gt;

&lt;p&gt;Add new domains to an existing certificate with argument &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--expand&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# certbot certonly --expand --cert-name example.com --webroot -w /var/www/log.example.com -d blog.example.com --dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But the it is recommended to abandon the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--expand&lt;/code&gt; option such that you can either add or remove domains by supplying a complete new list of domains to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d&lt;/code&gt; option.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# certbot certonly --cert-name example.com --webroot -w /var/www/log.example.com -d blog.example.com --dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After the above operation, the certificate &lt;em&gt;example.com&lt;/em&gt; only contains domain name &lt;em&gt;blog.example.com&lt;/em&gt;. It actually just creates a new certificate with the same name!&lt;/p&gt;

&lt;h2 id=&quot;renew-a-certificate&quot;&gt;Renew a Certificate&lt;/h2&gt;

&lt;p&gt;Let&apos;s Encrypt certificates expire after 90 days and can be renewed if a certificiate expires in less than 30 days. Renewing a certificate is actually to generate a new identical copy of the original certificate, using the same arguments which they are created with. The only difference is the expiration date is updated.&lt;/p&gt;

&lt;p&gt;Renewal just create a new certificate with the same name! So we can just re-run the command used to obtain the certificate, as in section &lt;a href=&quot;#obtain-a-certificate&quot;&gt;Obtain a Certificate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But sometimes, we need fine control over renewal. Certbot stores a renewal configuration for each certificate:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# realpath example.com.conf&lt;/span&gt;
/etc/letsencrypt/renewal/example.com.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A certificate can be manually renewed or automatically renewed.&lt;/p&gt;

&lt;h3 id=&quot;manual-renewal&quot;&gt;Manual Renewal&lt;/h3&gt;

&lt;p&gt;To interactively renew &lt;em&gt;all&lt;/em&gt; of your certificates, invoke the &lt;em&gt;renew&lt;/em&gt; subcommand.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# certbot -h renew&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cerbot renew --deploy-hook &quot;systemctl reload nginx.service&quot; --dry-run&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cerbot renew --deploy-hook /path/to/hook-script.sh --dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--deploy-hook&lt;/code&gt; will execute a program if and only if the certificate is successfully renewed. You can add the hook to its renewal configuration file.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/letsencrypt/renewal/example.com.conf
 
[renewalparams]
deploy_hook = systemctl reload nginx.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also put the hook into &lt;em&gt;/etc/letsencrypt/renewal-hooks/deploy/&lt;/em&gt;. For example, here is a hook script:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

systemctl reload nginx.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or more generally, you can put the hook in &lt;a href=&quot;#certbot-configuration&quot;&gt;Certbot Configuration&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;Once hooks is configured, just run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# cerbot renew --dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Renewal of &lt;a href=&quot;#standalone-authenticator&quot;&gt;standalone certificates&lt;/a&gt; requires port 80 to be available. In other words, Nginx should not listen on HTTP 80. If that&apos;s the case, you can stop Nginx first. Alternatively, we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--pre-hook&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--post-hook&lt;/code&gt; arguments.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# cerbot renew --pre-hook &quot;systemctl stop nginx&quot; --post-hook &quot;systemctl start nginx&quot; --dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attention please; unlike the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--deploy-hook&lt;/code&gt; hook, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--pre-hook&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--post-hook&lt;/code&gt; will be executed no matter of sucessful or failed renewal. Similarly, you can put the hooks into configuration files or script files.&lt;/p&gt;

&lt;h3 id=&quot;automatic-renwal&quot;&gt;Automatic Renwal&lt;/h3&gt;

&lt;p&gt;We can automate the process by &lt;em&gt;crontab&lt;/em&gt; or &lt;em&gt;systemd timer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Crontab:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /var/spool/cron/root&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# crontab -u root -e&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# crontab -u root -l&lt;/span&gt;

30 0,12 &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; /usr/bin/certbot renew &lt;span class=&quot;nt&quot;&gt;--quiet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Systemd timer:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# systemctl list-unit-files --type timer&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl status certbot-renew.timer&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable certbot-renew.timer&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl start certbot-renew.timer&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl list-timers -all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;certbot-renew.timer&lt;/em&gt; would invoke &lt;em&gt;certbot-renew.service&lt;/em&gt; automatically.&lt;/p&gt;

&lt;h2 id=&quot;backup-the-account-and-certificates&quot;&gt;Backup the Account and Certificates&lt;/h2&gt;

&lt;p&gt;Your account credentials have been saved in your Certbot configuration directory at &lt;em&gt;/etc/letsencrypt/&lt;/em&gt;. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal.&lt;/p&gt;

&lt;h2 id=&quot;share-certificates&quot;&gt;Share Certificates&lt;/h2&gt;

&lt;p&gt;Say we have obtained a certificate and configured auto-renewal on server A, but want to use the same certificate on server B. How to &lt;a href=&quot;https://stackoverflow.com/q/37391158&quot;&gt;achive this&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;Basically, we have two methods.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Write a &lt;a href=&quot;#manual-renewal&quot;&gt;deploy-hook&lt;/a&gt; to &lt;em&gt;rsync&lt;/em&gt; renewed certificate and key to server B.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Start from scratch on server B to obtain new certificate with the same procedure in this post. Don&apos;t worry about conflicts as obtaining a new certificate justs create a brand new one.&lt;/p&gt;

    &lt;p&gt;The only concern is the number limit of renewal per-certificate. Currently, Let&apos;s Encrypte allows 5 renewal per month for an individual certificate.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;deploy-certificates&quot;&gt;Deploy Certificates&lt;/h1&gt;

&lt;p&gt;You can update web server&apos;s SSL vhost configuration accordingly once the certificate is ready as below. We can follow &lt;a href=&quot;https://ssl-config.mozilla.org/&quot;&gt;Mozilla SSL Config Recommendation&lt;/a&gt; to get a secure and comptabile template.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;server {
    listen       443 ssl http2 default_server;
    listen       [::]:443 ssl http2 default_server;
    server_name  www.example.com;
    root         /usr/share/nginx/html;

    ssl_certificate &quot;/etc/letsencrypt/live/www.example.com/fullchain.pem&quot;;
    ssl_certificate_key &quot;/etc/letsencrypt/live/www.example.com/privkey.pem&quot;;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers PROFILE=SYSTEM;
    ssl_prefer_server_ciphers on;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then reload the web server:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# nginx -t&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl reload nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Additionaly, you can redirect all HTTP traffic to HTTPS:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;return 301 https://$server_name$request_uri;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This does not influence certificate renewal but may hinder new certificate application.&lt;/p&gt;

&lt;p&gt;If everything goes as expected, turn back on CDN coverage.&lt;/p&gt;

&lt;h1 id=&quot;ecdsa-certificate-and-rsa-certificate&quot;&gt;ECDSA Certificate and RSA Certificate&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;As of version 1.10, Certbot supports ECDSA certificates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When it comes to certificates and Signature Algorithms, we categorize them into Elliptic Curve Digital Signature Algorithm (ECDSA) certificate and RSA certificate. ECDSA certificate is also named Elliptic Curve Cryptography (ECC) cerficiate.&lt;/p&gt;

&lt;p&gt;The two kinds of certificate differ in the type of public/private keys. When generating a key pair, we can choose ECDSA algorithm or RSA algorithm. In return, the key algorithm affecrs almost any security operations, like encryption, signature etc.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://hackernoon.com/rsa-and-ecdsa-hybrid-nginx-setup-with-letsencrypt-certificates-ee422695d7d3&quot;&gt;ECDSA outweighs RSA&lt;/a&gt; in two ways:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Under certain level of security (in bits), ECDSA has much shorter key length.&lt;/li&gt;
  &lt;li&gt;Less CPU computation and networking load.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Therefore, it is always recommended to obtain a ECDSA certificate as it vastly reduce the time taken to perform TLS handshake and load web pages faster.&lt;/p&gt;

&lt;p&gt;For a long, Let&apos;s Encrypt does not support ECDSA certificate. However, the situation changed recdently (2020-09).&lt;/p&gt;

&lt;p&gt;To obtain a certificate from Let&apos;s Encrypt, we have to resort to other ACME clients &lt;a href=&quot;https://community.letsencrypt.org/t/certbot-support-for-ecdsa-certificates/132857&quot;&gt;other than Certbot&lt;/a&gt;. I choose &lt;a href=&quot;https://github.com/acmesh-official/acme.sh&quot;&gt;acme.sh&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When managing certificates with &lt;em&gt;acme.sh&lt;/em&gt;, please switch to &lt;em&gt;root&lt;/em&gt; instead of the &lt;em&gt;sudo&lt;/em&gt;, &lt;em&gt;su&lt;/em&gt; method.&lt;/p&gt;

&lt;p&gt;Firstly, we install &lt;em&gt;acme.sh&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# curl https://get.acme.sh | sh&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# ll ~/.acme.sh/&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# crontab -u root -l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, obtain an ECDSA certificate by &lt;a href=&quot;#webroot-authenticator&quot;&gt;Webroot Authenticator&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# acme.sh --issue -w /usr/share/nginx/html/ -d blog.example.com --keylength ec-256&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--keylength ec-256&lt;/code&gt; specifies the length of ECDSA key.&lt;/p&gt;

&lt;p&gt;How do I know if the certificate is ECDSA-based or RSA-based? Just check the &quot;Public Key Algorithm&quot; field, and make sure the field value is &lt;em&gt;id-ecPublicKey&lt;/em&gt;, as follows:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# openssl x509 -inform pem -noout -text -fingerprint -md5 &amp;lt; ~/.acme.sh/blog.example.com_ecc/blog.example.com.cer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You may find that, the public key is just 256-bit long.&lt;/p&gt;

&lt;p&gt;By default, everthing about &lt;em&gt;acme.sh&lt;/em&gt; is placed under &lt;em&gt;~/.acme.sh/&lt;/em&gt; by default. This directory is only for internal usage. To make use of the certificate, we should install the cert to Apache/Nginx etc.&lt;/p&gt;

&lt;p&gt;The following Nginx configuration is error-prone:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssl_certificate /root/.acme.sh/blog.example.com_cc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/blog.example.com_cc/blog.example.com.key;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nginx will report &lt;em&gt;permission&lt;/em&gt; error:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ # systemctl reload nginx

[emerg] BIO_new_file ... (SSL: error:0200100D:system library:fopen:Permission denied:fopen(&apos;/root/.acme.sh/blog.example.com_ecc/fullchain.cer&apos;,&apos;r&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Instead, execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--install-cert &amp;lt;domain&amp;gt;&lt;/code&gt; that will &lt;em&gt;copy&lt;/em&gt; the certificate and key into another directory, like:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /etc/acme.sh/blog.example.com_ecc&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# acme.sh --install-cert --ecc -d blog.example.com --cert-file /etc/acme.sh/blog.example.com_ecc/cert.pem --key-file /etc/acme.sh/blog.example.com_ecc/key.pem --fullchain-file /etc/acme.sh/blog.example.com_ecc/fullchain.pem --reloadcmd &quot;systemctl reload nginx.service&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The destination can be anywhare but the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d&lt;/code&gt; demands domain name. Attention please; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--ecc&lt;/code&gt; option tells &lt;em&gt;acme.sh&lt;/em&gt; to copy ECC certificate instead of RSA certificate, by looking for a directory with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_ecc&lt;/code&gt; suffix like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blog.example.com_ecc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;acme.sh&lt;/em&gt; maintains two copies of a certificate, one for internal usage, one for webserver. On the contrary, &lt;em&gt;certbot&lt;/em&gt; use symblic!&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--reloadcmd&lt;/code&gt; is critical to tell Nginx reload renewed certificates. Check &lt;em&gt;~/.acme.sh/en.example.com_ecc/en.example.com.conf&lt;/em&gt; , we will find the reload command is encoded by base64:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Le_ReloadCmd=&apos;__ACME_BASE64__START_c3lzdGVtY3RsIHJlbG9hZCBuZ2lueC5zZXJ2aWNl__ACME_BASE64__END_&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, update Nginx to make use of the copy of the certificate and key under &lt;em&gt;/etc/acme.sh/blog.example.com/&lt;/em&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>动态称球</title>
   <link href="/2017/10/01/weigh-ball/"/>
   <updated>2017-10-01T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/10/01/weigh-ball</id>
   <content type="html">&lt;h1 id=&quot;问题描述&quot;&gt;问题描述&lt;/h1&gt;

&lt;p&gt;有N个同规格的球，现发现其中有一个坏了，重量和其它N-1个球有稍微区别。现给一个没有砝码的灵敏天平，请通过最少次的称量，找出坏球，并判别是轻了还是重了。&lt;/p&gt;

&lt;h1 id=&quot;数学模型&quot;&gt;数学模型&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;给球编号，1,2, … , N.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;假设需要的最少次数是n，那么N和n之间的关系是：&lt;/p&gt;

    &lt;p&gt;n = ⌈ log₃(2N+3) ⌉ 或 N = ⌊ (3ⁿ - 3)/2 ⌋ (N &amp;gt;= 4)&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;这里出现两个特别的数字2和3. 2是因为每一个球有两个可能性，即它是坏球且比其它标准球轻，或它是坏球且比其它标准球重。3是因为每次称量会有三种结果，即左边重（右边轻），右边重（左边轻）或平衡。&lt;/li&gt;
      &lt;li&gt;我们说最少次数n，其实不是没次称量都要n次，因为称量过程是随机的，我们没法预测下一次称量的结果。但如果算法合理，最复杂的情况是n次；反之，算法不合理，最复杂情况不低于n次。&lt;/li&gt;
      &lt;li&gt;假设n不变，球数加1，即N+1个球，那么可以保证找出坏球，但不能保证识别出轻重。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;称量分析&quot;&gt;称量分析&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;称球的过程其实可以用决策树或矩阵方程表述。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;每次称量前，把待称量的球（假设K个，第一次为N）分成三堆，并确保上天平的两堆球数相同，也即：第一堆（左堆）⌈ K/3 ⌉个球，第二堆（右堆）⌈ K/3 ⌉个球，第三堆（未上称）K - 2⌈ K/3 ⌉个球。&lt;/p&gt;

    &lt;p&gt;这样的划分的结果是，不上天平的那堆球数少。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;前面说过，每次称量有三种可能，每种可能可以推导出新的信息：
    &lt;ol&gt;
      &lt;li&gt;左边重：坏球肯定在天平上的两堆里。坏球在左边并比标准球重，或坏球在右边且比标准球轻。&lt;/li&gt;
      &lt;li&gt;右边重：坏球肯定在天平上的两堆里。坏球在左边并比标准球轻，或坏球在右边且比标准球重。&lt;/li&gt;
      &lt;li&gt;平衡：坏球在未上称的第三堆，暂时无法判断轻重。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;每次称量前，我们需要算出：
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;如何根据上次称量结果，找出本次待称量的是哪些球。&lt;/p&gt;

        &lt;p&gt;假设上次称量结果为前两种情况（左边重或右边重，坏球在天平上），那么本次待称量的是天平上的球。假设上次称量的球数为K&apos;，那么本次K = 2⌈ K&apos;/3 ⌉. 如果上次称量结果为平衡，那么本次待称量即未上天平的第三堆，K = K&apos; - 2⌈ K&apos;/3 ⌉.&lt;/p&gt;

        &lt;p&gt;后面会分析到，“实际称量球数是待称量球的一个子集（&amp;lt;= K）”。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;分堆。如何决定一个编号球被分到哪一堆，或者说每一堆里都有哪些编号球。&lt;/p&gt;

        &lt;p&gt;决定了本次待称量的球，如何划分这些球才是核心问题，我们在下节讲解。&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;三堆&quot;&gt;三堆&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;第一次称量没有上次参考。待称量的是所有的N个球。只需按照编号顺序划分为：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;堆&lt;/th&gt;
          &lt;th&gt;球&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;1 ~ ⌈ N/3 ⌉&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;(⌈ N/3 ⌉ + 1) ~ 2⌈ N/3 ⌉&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;(2⌈ N/3 ⌉ + 1) ~ N&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;“否”表示未上天平的第三堆。第一次的分堆随意，只需要保证堆的数量即可。下面来考虑更一般的情况。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;假设本次待称量的球已经确定，这些球除了编号这个属性外，还额外增加了一个新标签，即前面节第二条所述三种推理。那么如何描述新信息呢？&lt;/p&gt;

    &lt;p&gt;本次待称量的球可以用u、v两个子集合表示，注意这里的u、v集合不是分堆，而是用来辅助分堆。我们也可以说u、v里的球具有u、v标签。&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;u里的球，要么是标准球，要么是坏球并且比标准球重。&lt;/li&gt;
      &lt;li&gt;v里的球，要么是标准球，要么是坏球并且比标准球轻。&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;u、v的定义可以反过来，但不影响结果。最简单的u、v集合出现在第一次称量之后：&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;第一次称量左重，则左堆为u，右边堆为v。&lt;/li&gt;
      &lt;li&gt;第一次称量右重，则右堆为u，左边堆为v。&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;这时| u | = | v | = ⌈ N/3 ⌉. 但更一般情况如下：&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;u、v有可能为空集；&lt;/li&gt;
      &lt;li&gt;| u | ≠ | v |更常见；&lt;/li&gt;
      &lt;li&gt;经过几轮称量后，堆里会同时含有u、v中的球，这是为了便于排除更多的球。&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;假设上次称量的三堆如下：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;堆&lt;/th&gt;
          &lt;th&gt;u&apos;,  v&apos;&lt;/th&gt;
          &lt;th&gt;数量&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;u₁&apos;, v₁&apos;&lt;/td&gt;
          &lt;td&gt;⌈ K&apos;/3 ⌉&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;u₂&apos;, v₂&apos;&lt;/td&gt;
          &lt;td&gt;⌈ K&apos;/3 ⌉&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;v&apos; 余下&lt;/td&gt;
          &lt;td&gt;K&apos; - 2⌈ K&apos;/3 ⌉&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;表格用逗号来分隔u/v集合，便于识别。&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;如果左重，那么u = u₁&apos;，v = v₂&apos;；u₂&apos;、v₁&apos;被排除；&lt;/li&gt;
      &lt;li&gt;如果右重，那么u = u₂&apos;，v = v₁&apos;；u₁&apos;、v₂&apos;被排除；&lt;/li&gt;
      &lt;li&gt;如果平衡，那么u = ∅，v = v&apos; - v₁&apos; - v₂&apos;引入一个标准球（左右堆里全是）。为何这里需要引入标准球？因为本次v&apos; - v₁&apos; - v₂&apos;集合球标签单一，引入标准球寻求更多差异。&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;轻特别注意如何排除部分“待称量球”，“实际称量球数是待称量球的一个子集（&amp;lt;= K）”。&lt;/p&gt;

    &lt;p&gt;显然，对于第一次称量没有前次参考，u = v = ∅.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;K = | u | + | v |. 那么把u、v里的球分成三堆呢？
    &lt;ol&gt;
      &lt;li&gt;把u集合的球平均分配到第一、二堆。如果不够⌈ K/3 ⌉，则&lt;/li&gt;
      &lt;li&gt;从v集合平均往第一、二堆放球到满。&lt;/li&gt;
      &lt;li&gt;把v里余下的球分到第三堆。明显不存在v集合取完后，还没有填完第一、二堆的情况。&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;至此分球完毕，用表格表示如下：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;堆&lt;/th&gt;
          &lt;th&gt;u,  v&lt;/th&gt;
          &lt;th&gt;数量&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;u₁, v₁&lt;/td&gt;
          &lt;td&gt;⌈ K/3 ⌉&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;u₂, v₂&lt;/td&gt;
          &lt;td&gt;⌈ K/3 ⌉&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;v余下&lt;/td&gt;
          &lt;td&gt;K - 2⌈ K/3 ⌉&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;开始本次称量。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;引入标准球
    &lt;ol&gt;
      &lt;li&gt;u = ∅，或v = ∅，或 u = v = ∅，此时引入标准球替换一个待称量球，寻取差异。被替换的待称量球放在第三堆。&lt;/li&gt;
      &lt;li&gt;一般发生在上次称量平衡时。但第一次称量时明显u = v = ∅. u = ∅, v ≠ ∅不常见，多出现在| u&apos; | 和 | v&apos; | 非常小时（如&amp;lt; =3）。&lt;/li&gt;
      &lt;li&gt;如果 | u | 或 | v | 非常小（如3），根本不引入标准球。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;n--123&quot;&gt;N = 1、2、3&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;N &amp;lt;= 3的情况特殊，这里特别说明。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;N = 1，不需要称，坏球肯定就那一个。&lt;/li&gt;
  &lt;li&gt;N = 2，没有参考，无法称量，&lt;/li&gt;
  &lt;li&gt;N = 3，n = 2。1号球左边，2号球右边，称量一次后用三号球替换2号球。
    &lt;ol&gt;
      &lt;li&gt;左重，左重，1号坏球并且比标准球重；&lt;/li&gt;
      &lt;li&gt;左重，平衡，2号坏球并且比标准球轻；&lt;/li&gt;
      &lt;li&gt;左重，右重，不可能；&lt;/li&gt;
      &lt;li&gt;平衡，左重，3号坏球并且比标准球轻；&lt;/li&gt;
      &lt;li&gt;平衡，平衡，不可能；&lt;/li&gt;
      &lt;li&gt;平衡，右重，3号坏球并且比标准球重；&lt;/li&gt;
      &lt;li&gt;右重，左重，不可能；&lt;/li&gt;
      &lt;li&gt;右重，平衡，2号球坏并且比标准球重；&lt;/li&gt;
      &lt;li&gt;右重，右重，1号球号并且比标准球轻；&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;n--4&quot;&gt;N = 4&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;n = ⌈ log₃(2*4+3) ⌉ = 3.&lt;/li&gt;
  &lt;li&gt;第一次称量，如上分析，没有参考，所以简单按编号分堆：
    &lt;ol&gt;
      &lt;li&gt;u&apos; = v&apos; = ∅.&lt;/li&gt;
      &lt;li&gt;⌈ K/3 ⌉ = ⌈ N/3 ⌉ = ⌈ 4/3 ⌉ = 2&lt;/li&gt;
    &lt;/ol&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;堆&lt;/th&gt;
          &lt;th&gt;u, v&lt;/th&gt;
          &lt;th&gt;数量&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;1 2&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;3 4&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;∅&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;分析下次称量u、v集合：&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;左重，u = { 1, 2 }, v = { 3, 4 }.&lt;/li&gt;
      &lt;li&gt;右重，u = { 3, 4 }, v = { 1, 2 }.&lt;/li&gt;
      &lt;li&gt;平衡，不可能。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;第二次称量：&lt;/p&gt;

    &lt;p&gt;K = | u | + | v | = 4，比较特殊K = K&apos;. ⌈ K/3 ⌉ = ⌈ 4/3 ⌉ = 2&lt;/p&gt;

    &lt;p&gt;一左重：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;堆&lt;/th&gt;
          &lt;th&gt;u, v&lt;/th&gt;
          &lt;th&gt;数量&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;1, 3&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;2, 4&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;∅&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;或一右重：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;堆&lt;/th&gt;
          &lt;th&gt;u, v&lt;/th&gt;
          &lt;th&gt;数量&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;3, 1&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;4, 2&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;∅&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;注意，这次不是按照顺序分堆。逗号左边是u集合，右边是v集合。&lt;/p&gt;

    &lt;p&gt;根据第一、二次称量，分析下次称量u、v集合，实际有4重情况：&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;一左重，二左重，u = { 1, 2 } ∩ { 1, 3 } = { 1 }，v = { 3, 4 } ∩ { 2, 4 } = { 4 }.&lt;/li&gt;
      &lt;li&gt;一左重，二右重，u = { 1, 2 } ∩ { 2, 4 } = { 2 }，v = { 3, 4 } ∩ { 1, 3 } = { 3 }.&lt;/li&gt;
      &lt;li&gt;一左重，二平衡，不可能。&lt;/li&gt;
      &lt;li&gt;一右重，二左重，u = { 3, 4 } ∩ { 3, 1 } = { 3 }，v = { 1, 2 } ∩ { 4, 2 } = { 2 }.&lt;/li&gt;
      &lt;li&gt;一右重，二平衡，不可能。&lt;/li&gt;
      &lt;li&gt;一右重，二右重，u = { 3, 4 } ∩ { 4, 2 } = { 4 }，v = { 1, 2 } ∩ { 3, 1 } = { 1 }.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;第二轮称量后，排除两个球，剩下两个球。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;第三次称量：&lt;/p&gt;

    &lt;p&gt;经过第二次称量，u、v cardinality为1, K = 2 &amp;lt; 4属于特殊情况。我们不需要继续称量分析，而是直接引入标准球。被排除的两个球肯定是标准球，随便引入一个替换u、v中的球上天平即可。&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;堆&lt;/th&gt;
          &lt;th&gt;u, v&lt;/th&gt;
          &lt;th&gt;数量&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;1,&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;, 4 &amp;gt; 2&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;∅&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;堆&lt;/td&gt;
          &lt;td&gt;u, v&lt;/td&gt;
          &lt;td&gt;数量&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;2,&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;, 3 &amp;gt; 1&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;∅&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;堆&lt;/td&gt;
          &lt;td&gt;u, v&lt;/td&gt;
          &lt;td&gt;数量&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;3,&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;, 2 &amp;gt; 4&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;∅&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;堆&lt;/td&gt;
          &lt;td&gt;u, v&lt;/td&gt;
          &lt;td&gt;数量&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;左&lt;/td&gt;
          &lt;td&gt;4,&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;右&lt;/td&gt;
          &lt;td&gt;, 1 &amp;gt; 3&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;否&lt;/td&gt;
          &lt;td&gt;∅&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;上表重，分别引入了2、1、4、3标准球作为参考：&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;左重，1是坏球并比标准球重；平衡，4是坏球并比标准球轻；右重不可能。&lt;/li&gt;
      &lt;li&gt;左重，2是坏球并比标准球重；平衡，3是坏球并比标准球轻；右重不可能。&lt;/li&gt;
      &lt;li&gt;左重，3是坏球并比标准球重；平衡，2是坏球并比标准球轻；右重不可能。&lt;/li&gt;
      &lt;li&gt;左重，4是坏球并比标准球重；平衡，1是坏球并比标准球轻；右重不可能。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;n--12&quot;&gt;N = 12&lt;/h1&gt;

&lt;p&gt;这个过程非常复杂，在&lt;a href=&quot;/assets/weigh-ball.docx&quot;&gt;纸上演练&lt;/a&gt;吧。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/weigh-ball.png&quot; alt=&quot;weigh 12 balls&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>firewalld</title>
   <link href="/2017/09/20/firewalld/"/>
   <updated>2017-09-20T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/09/20/firewalld</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#firewalld-and-iptables&quot; id=&quot;markdown-toc-firewalld-and-iptables&quot;&gt;firewalld and iptables&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#mask-iptables-service&quot; id=&quot;markdown-toc-mask-iptables-service&quot;&gt;mask iptables service&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#install&quot; id=&quot;markdown-toc-install&quot;&gt;Install&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#status&quot; id=&quot;markdown-toc-status&quot;&gt;Status&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#runtime-and-permanent&quot; id=&quot;markdown-toc-runtime-and-permanent&quot;&gt;Runtime and Permanent&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#service-and-port&quot; id=&quot;markdown-toc-service-and-port&quot;&gt;service and port&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#adding-ports&quot; id=&quot;markdown-toc-adding-ports&quot;&gt;Adding ports&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#adding-services&quot; id=&quot;markdown-toc-adding-services&quot;&gt;Adding services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#createmodify-services&quot; id=&quot;markdown-toc-createmodify-services&quot;&gt;Create/modify services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#disallow-ports&quot; id=&quot;markdown-toc-disallow-ports&quot;&gt;Disallow Ports&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#finally&quot; id=&quot;markdown-toc-finally&quot;&gt;Finally&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#refs&quot; id=&quot;markdown-toc-refs&quot;&gt;Refs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;firewalld-and-iptables&quot;&gt;firewalld and iptables&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://firewalld.org/&quot;&gt;Firewalld&lt;/a&gt; stack&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;iptables CLI -&amp;gt; iptables daemon -&amp;gt; kernel netfilter -&amp;gt; xtables/nftables. We should know the difference between a &lt;em&gt;service&lt;/em&gt; and shell &lt;em&gt;command&lt;/em&gt; in terms of &lt;em&gt;iptables&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;firewall-cmd CLI -&amp;gt; firewalld daemon -&amp;gt; iptables/nft CLI. Before firewalld 0.6.0, the underlying is &lt;em&gt;iptables&lt;/em&gt;, not it becomes &lt;em&gt;nft&lt;/em&gt;. Here is an illustration of before 0.6.0:&lt;/p&gt;

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

        &lt;p&gt;At the very top, sits the GUI tool.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Specially, firewalld introduces &lt;em&gt;zone&lt;/em&gt; to defines the level of trust for a connection, IP source or interface, which resembles Microsoft Windows firewall. Rules are created within a zone. A zone is bound to one or more interfaces, IP sources or interfaces, but a connection, interface or IP source can &lt;em&gt;only&lt;/em&gt; be part of one zone.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;mask-iptables-service&quot;&gt;mask iptables service&lt;/h1&gt;

&lt;p&gt;Switch to firewalld.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# systemctl stop iptables-services&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# sysremctl disable iptables-services&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl mask iptables-services&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;install&quot;&gt;Install&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum install iptables firewalld&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable firewalld&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl start firewalld&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl status firewalld&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Don&apos;t break SSH connection as the default SSH port in default zone is 22 that is usually changed by administrator, otherwise you could no longer SSH into server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;status&quot;&gt;Status&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --reload&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --state&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# print zone names&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --get-zones&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# print all zone details&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --list-all-zones&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# default is &apos;pulbic&apos;&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --get-default-zone&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# zones that has bindings&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --get-active-zone&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# print all service names&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --get-services&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# print a service detail&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --info-service https&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# print objects in a zone&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --zone=public --list-services&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --zone=public --list-ports&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --zone=public --list-interfaces&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --zone=public --list-sources&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# print all objects in a zone&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --zone=public --list-all&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --info-zone public&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Default zone is &lt;em&gt;public&lt;/em&gt; to which unmatched traffic would be applied.&lt;/p&gt;

    &lt;p&gt;For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We &lt;em&gt;activate&lt;/em&gt; a zone (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--get-active-zones&lt;/code&gt;) by binding a network interface, source IP address range(s) or ports to it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As &lt;em&gt;firewalld&lt;/em&gt; sites on top of &lt;em&gt;iptables&lt;/em&gt;, we can manipulate underlying &lt;em&gt;iptables&lt;/em&gt; rules with &lt;em&gt;firewall-cmd&lt;/em&gt; directly with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--direct&lt;/code&gt; option.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --direct --get-all-chains&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --direct --get-chains nat&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --direct --get-all-rules&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --direct --get-rules nat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attention please; do not use &lt;em&gt;iptables&lt;/em&gt; command to manipulate &lt;em&gt;firewalld&lt;/em&gt; rules as that would make things complicated.&lt;/p&gt;

&lt;h1 id=&quot;runtime-and-permanent&quot;&gt;Runtime and Permanent&lt;/h1&gt;

&lt;p&gt;When updating &lt;em&gt;firewalld&lt;/em&gt; rules, option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--permanent&lt;/code&gt; does not affect runtime rules but write to disk for accross boot.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;When &lt;a href=&quot;#disallow-ports&quot;&gt;changing&lt;/a&gt; something, do not add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--permanent&lt;/code&gt; option and add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--timeout&lt;/code&gt; option to have a test, especially when you change the SSH port or disallow a port.&lt;/li&gt;
  &lt;li&gt;After that either execute the update again with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--permanent&lt;/code&gt; option or run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;firewall-cmd --runtime-to-permanent&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#finally&quot;&gt;Reload rules&lt;/a&gt; into runtime if step 1 is skipped.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;service-and-port&quot;&gt;service and port&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Services are pre-defined well-known ports like http, https etc.&lt;/p&gt;

    &lt;p&gt;Check &lt;em&gt;/usr/lib/firewalld/services&lt;/em&gt; XML definitions. You shouldn&apos;t edit those files.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To edit a servce (i.e. change ssh port):&lt;/p&gt;

    &lt;p&gt;Copy &lt;em&gt;/usr/lib/firewalld/services/ssh.xml&lt;/em&gt; to &lt;em&gt;/etc/firewalld/services/&lt;/em&gt;; change port there.&lt;/p&gt;

    &lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;service&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;short&amp;gt;&lt;/span&gt;SSH&lt;span class=&quot;nt&quot;&gt;&amp;lt;/short&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;description&amp;gt;&lt;/span&gt;Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;port&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;protocol=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tcp&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;port=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;12345&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/service&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Alternatively, adding port directly to default zone.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;adding-ports&quot;&gt;Adding ports&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --zone=public --add-port=12345/tcp&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --reload (opt)&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --zone=public --add-port=12345/tcp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Take effect immediately at rumtine without &lt;em&gt;reload&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;As we have the runtime command at first, no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--reload&lt;/code&gt; is required.&lt;/li&gt;
  &lt;li&gt;Take effect accross &lt;em&gt;reload&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--zone&lt;/code&gt; can be ommited unless you want to change other zones.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;adding-services&quot;&gt;Adding services&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --zone=public --add-service=http --add-service=https&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;createmodify-services&quot;&gt;Create/modify services&lt;/h1&gt;

&lt;p&gt;Only a permanent service can be created.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --new-service-from-file=/path/to/service.xml --name=myservice (using an existing service)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --new-service=myservice (create an empty service)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --info-service=myservice&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Modify it after creation:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --service=myservice --set-description=description&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --service=myservice --set-short=description&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --service=myservice --add-port=portid[-portid]/protocol&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --service=myservice --remove-port=portid[-portid]/protocol&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --info-service=myservice&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding the new service to a zone:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --zone=public --add-service=myservice&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I think the easiest way is to copy an existing service XML to &lt;em&gt;/etc/firewalld/services/myservice.xml&lt;/em&gt; and edit that file directly.&lt;/p&gt;

&lt;h1 id=&quot;disallow-ports&quot;&gt;Disallow Ports&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# drop zone&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# test&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --zone=drop --add-port=12345/tcp --timeout 5m&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# permanent&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --zone=drop --add-port=12345/tcp&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# default zone&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# test&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --zone=public --remove-port=12345/tcp --timeout 5m&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# permanent&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --permanent --zone=public --add-port=12345/tcp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, the &lt;em&gt;drop&lt;/em&gt; zone is not &lt;a href=&quot;#status&quot;&gt;activated&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;finally&quot;&gt;Finally&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# firewall-cmd --reload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-using-firewalld-on-centos-7&quot;&gt;firewalld centos 7&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.linuxjournal.com/content/understanding-firewalld-multi-zone-configurations&quot;&gt;Understanding Firewalld in Multi-Zone Configurations&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>32-bit Android-x86 5.1-rc1</title>
   <link href="/2017/08/25/android-x86/"/>
   <updated>2017-08-25T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/08/25/android-x86</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post describe customzing &lt;em&gt;android-x86-5.1-rc1.iso&lt;/em&gt; and using tips. Regarding the installation, please refer to &lt;a href=&quot;/2015/08/21/virtualbox&quot;&gt;virtualbox post&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/assets/android-x86.jpg&quot; alt=&quot;readme&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;customization&quot;&gt;Customization&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Download &lt;a href=&quot;http://www.android-x86.org/&quot;&gt;android-x86-5.1-rc1.iso&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;virtual/cdrtools&lt;/em&gt; offers many tools to operates on ISO image, including &lt;em&gt;mkisofs&lt;/em&gt; creating bootable ISO.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file android-x86-5.1-rc1.iso
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;isoinfo &lt;span class=&quot;nt&quot;&gt;-pd&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-debug&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; android-x86-5.1-rc1.iso
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;isoinfo &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; android-x86-5.1-rc1.iso
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;iso-info &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; ERROR &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; android-x86-5.1-rc1.iso
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mount ISO.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /mnt/android-x86&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# mount -t loop /path/to/android-x86-5.1-rc1.iso /mnt/android-x86&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Get &lt;em&gt;system.sfs&lt;/em&gt; which is a Squashfs (compressed read-only for Linux) that containing the Android &lt;em&gt;/system&lt;/em&gt; partition - our customzation target in this post.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mount Squashfs.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /mnt/squashfs&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# mount -t squashfs -o loop /mnt/android-x86/system.sfs /mnt/squashfs&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Make sure *sys-fs/squashfs-tools* is installed.&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# unsquashfs [-ll] -d /mnt/squashfs /mnt/android-x86/system.sfs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;There exists only one file &lt;em&gt;system.img&lt;/em&gt; which is the image of original &lt;em&gt;/system&lt;/em&gt; mountpoint of Android-x86. That is to say, the author first create Android &lt;em&gt;/system&lt;/em&gt; partition as image and then compress it as Squashfs.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mount image.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /mnt/img&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# mount -t ext4 -o loop /mnt/squashfs/system.img /mnt/img&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Either&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cp -a img /home/username/workspace/ (rsync -a img /home/username/workspace/)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# chown -R username: /home/username/workspace/img/&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /home/username/workspace/img
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cd /mnt&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cp squashfs/system.img .&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# make temp_img&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# mount -t ext4 -o loop,rw system.img temp_img&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;We cannot modify &lt;em&gt;/mnt/img&lt;/em&gt; since it&apos;s directly mounted from read-only Squashfs.&lt;/li&gt;
      &lt;li&gt;Do &lt;a href=&quot;https://stackoverflow.com/a/2194500&quot;&gt;&lt;strong&gt;NOT&lt;/strong&gt;&lt;/a&gt; add trailing slash to &lt;em&gt;/mnt/img&lt;/em&gt; when &lt;em&gt;rsync&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Do customization here under &lt;em&gt;/home/username/workspace/img&lt;/em&gt;. For example, remove LatinIME, SetupWizard etc. etc. Especially for &lt;em&gt;build.prop&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ro.product.locale.language=zh
ro.product.locale.region=CN
# ro.product.cpu.abilist64=x86_64, arm64-V8A,x86,armeabi-v7a, armeabi
dalvik.vm.heapstartsize=8m
dalvik.vm.heapgrowthlimit=150m
dalvik.vm.heapsize=256m
# ro.com.google.gmsversion=5.1_r2
# ro.com.google.clientidbase=android-asus
# ro.com.google.clientidbase.ms=android-asus
# ro.com.google.clientidbase.am=android-asus
# ro.com.google.clientidbase.gmm=android-asus
# ro.com.google.clientidbase.yt=android-asus
# ro.setupwizard.mode=OPTIONAL (DISABLED, or REQUIRED)
dalvik.vm.execution-mode=int:fast
ro.sf.lcd_density=130
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;For 64-bit, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arm64-V8A&lt;/code&gt; &lt;a href=&quot;https://groups.google.com/d/topic/android-x86/XY39sISdRJY&quot;&gt;precdes&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x86&lt;/code&gt; in &lt;em&gt;abilist&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;DPI can be changed on-the-fly; please read the Tips part below.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;&lt;em&gt;system/app&lt;/em&gt;:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;BasicDreams/ Bluetooth/ Browser/ Calculator/ Calendar/ Camera2/ CaptivePortalLogin/ ConfigUpdater/ DeskClock/ Email/ Exchange2/ Galaxy4/ Gallery2/ Gmail2/ GoogleC* HTMLViewer/ HoloSpiralWallpaper/ KeyChain/ LatinIME/ LiveWallpapers* Music2/ NotePad/ PhaseBeam/ PicoTts/ PrintSpooler/ QuickSearchBox/ RSSReader/ SoundRecorder/ UserDictionaryProvider/ VisualizationWallpapers/ YouTube/&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;&lt;em&gt;system/priv-app&lt;/em&gt;:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;CalendarProvider/ Contacts* FusedLocation/ GmsCore/ Google* ManagedProvisioning/ MusicFX/ Phonesky/ TSCalibration2/ WallpaperCropper/&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;&lt;em&gt;/fonts&lt;/em&gt;: all &lt;em&gt;NotoSans*.ttf&lt;/em&gt; except &lt;em&gt;NotoSansSymbols-Regular-Subsetted.ttf&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;usr/idc&lt;/em&gt;: refer to Double Mouse below.&lt;/p&gt;

    &lt;p&gt;Customization finished. Then we should re-pack the ISO file.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Do &lt;strong&gt;NOT&lt;/strong&gt; unmount.&lt;/p&gt;

    &lt;p&gt;If you choose to the alternative method (mounting &lt;em&gt;system.img&lt;/em&gt; file as &lt;em&gt;rw&lt;/em&gt;), do not &lt;em&gt;umount&lt;/em&gt; now. Upon custiomization finished, intuitively, we should &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;umount ~/workspace/img&lt;/code&gt;, which is fine but far from perfect. For example, we cannot resize (read the next step &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-l 700M&lt;/code&gt;) image although we removed bunch of built-in apks.&lt;/p&gt;

    &lt;p&gt;What we should do is to creating a new image.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Require furtuer verification.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;make_ext4fs&lt;/em&gt; and &lt;em&gt;simg2img&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;To continue the following procedures, we must manually compile &lt;em&gt;make_ext4fs&lt;/em&gt; and/or &lt;em&gt;simg2img&lt;/em&gt; from Android-x86-5.1-rc1 source. Binaries got from web would probably be troublesome. For example, &lt;a href=&quot;https://github.com/superr/make_ext4fs&quot;&gt;make_ext4fs&lt;/a&gt; comes out of AOSP 6.0.1 source, &lt;em&gt;make_ext4fs&lt;/em&gt; compiled from which would cause Android-x86-5.1-rc1 losing network and SuperSU.&lt;/p&gt;

    &lt;p&gt;When creating image file, &lt;em&gt;make_ext4fs&lt;/em&gt; sets file permissions in accord with &lt;em&gt;core/include/private/android_filesystem_config.h&lt;/em&gt; irrepsective of that in working directory. Therefore, file permissions is fixed in &lt;em&gt;make_ext4fs&lt;/em&gt; binary. That is the reason we must compile &lt;em&gt;make_ext4fs&lt;/em&gt; from the correct Android source of your image.&lt;/p&gt;

    &lt;p&gt;To compile &lt;em&gt;make_ext4fs&lt;/em&gt; we should get source of &lt;em&gt;core&lt;/em&gt;, &lt;em&gt;extras&lt;/em&gt; and additionally &lt;em&gt;zlib&lt;/em&gt; and &lt;em&gt;libselinux&lt;/em&gt;. Android-x86 fetch the later two &lt;a href=&quot;https://sourceforge.net/p/android-x86/manifest/ci/lollipop-x86/tree/default.xml&quot;&gt;from official AOSP&lt;/a&gt;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;tools
&lt;span class=&quot;c&quot;&gt;# remove everything except *core/{include/private,libsparse}*&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; lollipop-x86 https://git.code.sf.net/p/android-x86/system_core core
&lt;span class=&quot;c&quot;&gt;# remove everything except *extras/ext4_utils*&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; lollipop-x86 https://git.code.sf.net/p/android-x86/system_extras extras
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; android-5.1.1_r30 https://android.googlesource.com/platform/external/zlib zlib
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; android-5.1.1_r30 https://android.googlesource.com/platform/external/libselinux libselinux
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Makefile:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
SELIB = libselinux
ZLLIB = zlib/src
SPLIB = core/libsparse
COLIB = core
MALIB = extras/ext4_utils

all:
    $(MAKE) -C $(SELIB)/src all
    $(MAKE) -C $(ZLLIB) all
    $(MAKE) -C $(SPLIB) libsparse.a
    $(MAKE) -C $(MALIB) all
    mv $(MALIB)/make_ext4fs make_ext4fs

clean:
    $(MAKE) -C $(SELIB)/src clean
    $(MAKE) -C $(ZLLIB) clean
    $(MAKE) -C $(SPLIB) clean
    $(MAKE) -C $(MALIB) clean
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Then we get &lt;em&gt;make_ext4fs&lt;/em&gt; binary. For &lt;em&gt;simg2img&lt;/em&gt;, just grab one from web since it&apos;s compatibable.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/superr/make_ext4fs&quot;&gt;make_ext4fs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/anestisb/android-simg2img&quot;&gt;simg2img&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/ASdev/android_img_repack_tools&quot;&gt;android_img_repack_tools&lt;/a&gt; which is recommended.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://gist.github.com/shakalaca/4942cfb8a4869325cdc9&quot;&gt; Howto: compile mkbootimg/mkbootfs/make_ext4fs on OS X&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/q/26589111&quot;&gt;UnPack / rePack android img with Ubuntu simg2img/make_ext4fs&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;New image&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Create *sparse* format image&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make_ext4fs &lt;span class=&quot;nt&quot;&gt;-T&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; 700M &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; system system_sparse.img img
&lt;span class=&quot;c&quot;&gt;# Convert Android sparse image to raw image.&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;simg2img system_sparse.img system_raw.img &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;If&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; supplied to &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;make_ext4fs&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file system_sparse.img system_raw.img&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mv &lt;/span&gt;system_raw.img system.img
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;blockquote&gt;
      &lt;p&gt;You are recommended to omit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-s&lt;/code&gt; argument and &lt;em&gt;simg2img&lt;/em&gt; as &lt;em&gt;sparse&lt;/em&gt; image format is for Android but Android-x86 (Android-x86 uses Linux RAW image).&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;ol&gt;
      &lt;li&gt;&apos;l&apos;: new smaller image size.&lt;/li&gt;
      &lt;li&gt;&apos;s&apos;: sparse mode to compress image file.&lt;/li&gt;
      &lt;li&gt;&apos;a&apos;: mount point at Android.&lt;/li&gt;
      &lt;li&gt;Check the new image file size, it&apos;s exactly 700M.&lt;/li&gt;
      &lt;li&gt;&apos;T&apos;: time 0 means 1970-1-1.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;New Squashfs&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;We cannot mount Squashfs as &lt;em&gt;rw&lt;/em&gt;. Must create new Squashfs like image above.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mksquashfs system.img system.sfs &lt;span class=&quot;nt&quot;&gt;-force-uid&lt;/span&gt; 1001 &lt;span class=&quot;nt&quot;&gt;-force-gid&lt;/span&gt; 1001
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Re-pack &lt;a href=&quot;https://fedoraproject.org/wiki/User:Pjones/BootableCDsForBIOSAndUEFI&quot;&gt;BootableCDsForBIOSAndUEFI&lt;/a&gt;&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;We cannot &lt;em&gt;mount&lt;/em&gt; ISO as &lt;em&gt;rw&lt;/em&gt;. Though we can use Archive manager to modify ISO contents, &lt;em&gt;bootable&lt;/em&gt; information gets lost meanwhile, resulting in ISO unbootable.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rsync -a --exclude=&quot;system.sfs&quot; /mnt/android-x86 /home/username/workspace/ (cp -a android-x86 temp_android-x86)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# chown -R username: /home/username/workspace/android-x86&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; system.sfs android-x86/
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;android-x86/
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkisofs &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Android-x86-5.1-rc1&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Android-x86-5.1-rc1&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-volset&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Android-x86-5.1-rc1&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-input-charset&lt;/span&gt; utf-8 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; ../android-x86.iso &lt;span class=&quot;nt&quot;&gt;-JlrTUv&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; isolinux/isolinux.bin &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; isolinux/boot.cat &lt;span class=&quot;nt&quot;&gt;-no-emul-boot&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-boot-load-size&lt;/span&gt; 4 &lt;span class=&quot;nt&quot;&gt;-boot-info-table&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eltorito-alt-boot&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; boot/grub/efi.img &lt;span class=&quot;nt&quot;&gt;-no-emul-boot&lt;/span&gt; ./
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; means that we want to use Rockridge extensions. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt; command line option also achieves this but in a less satisfactory way. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt; maintains the UID and GID of each file&apos;s owner. The same UID and GID will more than likely be meaningless once the files are transported over to another system, so ownership of all files in the ISO image is set to &lt;em&gt;root:root&lt;/em&gt; if we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt;. Also, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt; preserves file permissions, including the &lt;em&gt;write&lt;/em&gt; flags. Having any of the &lt;em&gt;write&lt;/em&gt; flags set for a file on a read-only media doesn&apos;t make much sense, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r&lt;/code&gt; resets it in the filesystem image.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-U&lt;/code&gt; may need removed.&lt;/li&gt;
      &lt;li&gt;New &lt;em&gt;mkisofs&lt;/em&gt; version abandons &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e&lt;/code&gt; option.&lt;/li&gt;
      &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-m&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-x&lt;/code&gt; now works identically to exlucde leftovers.&lt;/li&gt;
      &lt;li&gt;Android-x86-5.1-rc1 (32 bits) ISO file does not have &lt;em&gt;efi.img&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Refs&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;http://d846224089.lofter.com/post/1cc5ca4e_b7a25ab&quot;&gt;must read&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://www.tuxfixer.com/mount-modify-edit-repack-create-uefi-iso-including-kickstart-file/&quot;&gt;Mount Modify Edit Repack Create UEFI ISO&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://gist.github.com/jhorstmann/1579903&quot;&gt;How to modify android-x86 asus_laptop imag&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://bencane.com/2013/06/12/mkisofs-repackaging-a-linux-install-iso/&quot;&gt;Repackaging a Linux installation DVD using mkisofs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://linuxpitstop.com/edit-iso-files-using-mkisofs-in-linux/&quot;&gt;Modify/Edit/Re-pack ISO Files Using Mkisofs In Linux&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;tips&quot;&gt;&lt;a href=&quot;https://www.kirsle.net/blog/entry/android-4-0-in-virtualbox&quot;&gt;Tips&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;By switching to virtual terminal (F1 - F6), we get &lt;em&gt;root&lt;/em&gt; shell.&lt;/li&gt;
  &lt;li&gt;If you are away from VB, the &lt;em&gt;right menu&lt;/em&gt; (between the right Alt and right Ctrl keys), ESC, left, right, up and down keys wakes up Android-x86 from powersave mode.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;hostonly&quot;&gt;Hostonly&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;/2015/08/21/virtualbox&quot;&gt;hostonly&lt;/a&gt; might not able to &lt;em&gt;ping&lt;/em&gt; guest while the reverse direction works. Probably, check both the host and guest &lt;em&gt;arp&lt;/em&gt; table.
    &lt;ol&gt;
      &lt;li&gt;I previously set &lt;em&gt;dhcpcd.conf&lt;/em&gt; with &lt;em&gt;noarp&lt;/em&gt;, resulting outdated &lt;em&gt;arp&lt;/em&gt; table (also try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arp -d/a&lt;/code&gt;).&lt;/li&gt;
      &lt;li&gt;Dunno why, &lt;em&gt;hostonly&lt;/em&gt; networking is unreliable, ocassionally cannot &lt;em&gt;ping&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

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

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# adb tcpip 5555 (on android-x86)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# adb -e connect 192.168.56.101:5555&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# adb root&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# adb -e connect 192.168.56.101:5555&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# adb shell&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;shutdown&quot;&gt;Shutdown&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# https://sourceforge.net/p/android-x86/kernel/ci/kernel-4.4/tree/kernel/reboot.c&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Alt-F1&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# reboot -f/p (shutdown)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# reboot (reboot)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;reset&quot;&gt;Reset&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Alt-F1&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rm -R /data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;dpi&quot;&gt;DPI&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;su
~ &lt;span class=&quot;c&quot;&gt;# wm density&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# wm density 200 &amp;amp;&amp;amp; reboot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adjust the value as you wish.&lt;/p&gt;

&lt;h2 id=&quot;double-mouse&quot;&gt;&lt;a href=&quot;https://groups.google.com/d/topic/android-x86/0XmX3b0f1IE/discussion&quot;&gt;Double Mouse&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;To remove the &lt;em&gt;duplicate mouse&lt;/em&gt; issue, firstly, set VM mouse device to &lt;em&gt;usbtablet&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vboxmanage modifyvm Android-x86 &lt;span class=&quot;nt&quot;&gt;--mouse&lt;/span&gt; usbtablet
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You may found one of the mouse changes to draggable &lt;em&gt;circle&lt;/em&gt;. Then, we further create an &lt;a href=&quot;https://source.android.com/devices/input/input-device-configuration-files&quot;&gt;Input Device Configuration&lt;/a&gt; file for the &lt;em&gt;usbtablet&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Get into Android terminal:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ $ su
~ # cd /system/usr/idc
~ # dumpsys input | less
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From the output of &lt;em&gt;dumpsys input&lt;/em&gt; you can easily find the Virtualbox Usbtablet device however the &lt;em&gt;devicetype&lt;/em&gt; is &lt;em&gt;pointer&lt;/em&gt; instead of correct &lt;em&gt;touchscreen&lt;/em&gt;. What we do is to create a configureation under &lt;em&gt;/system/usr/idc&lt;/em&gt; to tell Android how to use the device correctly.&lt;/p&gt;

&lt;p&gt;The configureation file can be grabbed from &lt;em&gt;Android-x86-4.4-r5.iso&lt;/em&gt; system (&lt;em&gt;/system/usr/idc/GenericTouch.idc&lt;/em&gt;). If you want to skip all that trouble, here is it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Copyright (C) 2011 The Android-x86 Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Basic Parameters
touch.deviceType = touchScreen
#touch.orientationAware = 1

# Touch Size
touch.touchSize.calibration = default

# Tool Size
touch.toolSize.calibration = default

# Pressure
touch.pressure.calibration = default

# Size
touch.size.calibration = default

# Orientation
touch.orientation.calibration = none

device.internal = 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We should change the filename to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Vendor_XXXX_Product_XXXX_Version_XXXX.idc&lt;/code&gt; as directed, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XXXX&lt;/code&gt; comes out of &lt;em&gt;dumpsys input&lt;/em&gt; output.&lt;/p&gt;

&lt;p&gt;Put the newly created file to &lt;em&gt;/system/usr/idc&lt;/em&gt;. &lt;strong&gt;Attention&lt;/strong&gt;, make sure the file has &lt;em&gt;read&lt;/em&gt; permission.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ # chmod 644 Vendor_XXXX_Product_XXXX_Version_XXXX.idc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;skip-setupwizard&quot;&gt;Skip SetupWizard&lt;/h2&gt;

&lt;p&gt;The first time Android starts up, you might fail to bypass Google account setup even Wi-Fi setup is skipped. This was the VM NAT does connect to the Internet but Android think it&apos;s Wi-Fi, and meanwhile Google was blocked, which make Android try to connect to the &lt;em&gt;fake&lt;/em&gt; Wi-Fi endlessly. The solution:&lt;/p&gt;

&lt;p&gt;Click the upleft, upright, downright, and downleft corners of Android&apos;s effective launcher (not your computer screen) &lt;em&gt;sequentially&lt;/em&gt;. That&apos;s it.&lt;/p&gt;

&lt;p&gt;Another way is turn off NAT temporarily.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vboxmanage controlvm Android51 setlinkstate1 off
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;resolution&quot;&gt;Resolution&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Set a proper resolution value make Android-x86 run far more smoothly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Create temporary Grub menu&lt;/p&gt;

    &lt;p&gt;During booting, &lt;em&gt;e&lt;/em&gt; enters edit mode; &lt;em&gt;e&lt;/em&gt; edits selected &lt;em&gt;kernel&lt;/em&gt; line; append &lt;em&gt;vga=ask&lt;/em&gt;; enter; &lt;em&gt;b&lt;/em&gt; to boot; &quot;ENTER&quot; to see available resolution; &lt;em&gt;scan&lt;/em&gt; to include self-defined value (next section below). Each resolution has hex number prefix. For example, 800x600 responds to 0x314 (decimal 788).&lt;/p&gt;

    &lt;p&gt;Input one of the hex prefix to test. If none of the default resolution fits reuirement, define one by &lt;em&gt;vboxmanage&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Self-defined resolution&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage setextradata Android-x86 &lt;span class=&quot;s2&quot;&gt;&quot;CustomVideoMode1&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;405x720x16&quot;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage setextradata Android-x86 &lt;span class=&quot;s2&quot;&gt;&quot;CustomVideoMode2&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;800x600x16&quot;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage setextradata Android-x86 &lt;span class=&quot;s2&quot;&gt;&quot;CustomVideoMode2&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;remove this entry&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;For Android 6.0 and above, use 32-bit color instead of 16.&lt;/li&gt;
      &lt;li&gt;Add more by CustomVideoMode2, CustomVideoMode3 etc.&lt;/li&gt;
      &lt;li&gt;This command will update &lt;em&gt;*.vbox&lt;/em&gt; file.&lt;/li&gt;
      &lt;li&gt;Type &lt;em&gt;scan&lt;/em&gt; to show self-defined value and relavent hex prefix.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Debug mode&lt;/p&gt;

    &lt;p&gt;During boot, entering Grub debug mode,&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mount -o remount,rw /mnt&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cd /mnt/grub&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# vi menu.lst&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Add a boot entry, adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vga=desired-decimal-prefix&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UVESA_MODE=desired-resolution&lt;/code&gt; to &lt;em&gt;kernel&lt;/em&gt; line.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;vga&lt;/em&gt; value in &lt;em&gt;menu.lst&lt;/em&gt; should be decimal while in temporary boot edit mode be hex.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;Use &lt;em&gt;wm size&lt;/em&gt; checks resolution.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;wm overscan 3,4,3,4&lt;/em&gt; simulates mobile edge margins.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Nextcloud</title>
   <link href="/2017/08/05/nextcloud/"/>
   <updated>2017-08-05T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/08/05/nextcloud</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Nextcloud is open source platform serving file (private cloud disk), contacts, calendar synchronization ans sharing. By Nextcloud, you control your information, being not subject to privacy leak.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;requirements--lnmp&quot;&gt;&lt;a href=&quot;https://docs.nextcloud.com/server/12/admin_manual/installation/source_installation.html&quot;&gt;Requirements -LNMP&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;L: CentOS 7 64-bit;&lt;/li&gt;
  &lt;li&gt;N: &lt;a href=&quot;/2017/04/11/nginx/&quot;&gt;Nginx&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;M: MariaDB;&lt;/li&gt;
  &lt;li&gt;P: Php-FPM.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;

&lt;p&gt;Administration work can be done:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Web UI;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.nextcloud.com/server/13/admin_manual/configuration_server/occ_command.html&quot;&gt;&lt;em&gt;occ&lt;/em&gt;&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;Edit configuration file manually.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;mariadb&quot;&gt;MariaDB&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum install mariadb mariadb-server&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl status mariadb&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl start mariadb&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable mariadb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;mariadb-configuration&quot;&gt;MariaDB configuration&lt;/h2&gt;

&lt;p&gt;Create password for MariaDB &lt;em&gt;root&lt;/em&gt; user:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ # mysql_secure_installation
Enter current password for root (enter for none): # just ENTER
Set root password? [Y/n] Y
New password: 
Re-enter new password: 
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the MariaDB root password just set, now we can login to the &lt;em&gt;mysql&lt;/em&gt; shell to create a database and a user for Nextcloud.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ # mysql -u root -pPassword
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 14
Server version: 5.5.52-MariaDB MariaDB Server

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type &apos;help;&apos; or &apos;\h&apos; for help. Type &apos;\c&apos; to clear the current input statement.

MariaDB [(none)]&amp;gt; help
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now &lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-create-and-manage-databases-in-mysql-and-mariadb-on-a-cloud-server&quot;&gt;creating&lt;/a&gt; database and user with SQL within SQL shell:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;create database nc_db
# or
create database nc_db default character set utf8mb4 collate utf8mb4_unicode_ci;
create user nc_user@localhost identified by &apos;password&apos;;
grant all privileges on nc_db.* to nc_user@localhost identified by &apos;password&apos;;
flush privileges;
show databases;
show tables from nc_db;
select user,host,password,plugin from mysql.user;
show grants for nc_user@localhost;
quit;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Create a database and user for Nextcloud service. Grant all privileges of the database to the user.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If the user account does exist and you provide the IDENTIFIED BY clause, the user&apos;s password will be changed.&lt;/p&gt;

    &lt;p&gt;So use the same &apos;password&apos; value in case of losing it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;php-fpm&quot;&gt;Php-fpm&lt;/h1&gt;

&lt;p&gt;Make sure &lt;a href=&quot;/2017/04/05/centos7/&quot;&gt;webtatic repository&lt;/a&gt; is enabled and check &lt;a href=&quot;https://webtatic.com/packages/php70/&quot;&gt;webtatic packages&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum --enablerepo=webtatic install php70w-fpm php70w-common&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum --enablerepo=webtatic install php70w-ctype php70w-dom php70w-gd php70w-iconv php70w-json php70w-libxml php70w-mbstring php70w-posix php70w-simplexml php70w-xmlreader php70w-xmlwriter php70w-zip php70w-zlib&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum --enablerepo=webtatic install php70w-mysql php70w-curl php70w-intl php70w-mcrypt php70w-opcache php70w-pecl-apcu&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# php -v/i&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# php -m | grep -i apcu&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Some Php modules (i.e. php-70w-curl) does not exist but enclosed by another module (i.e. php70w-common).&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;opcache&lt;/em&gt; module won&apos;t be installed without explicit pointing out, which would cause &lt;a href=&quot;https://github.com/nextcloud/server/issues/5249&quot;&gt;APCu memory exhausted issue&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;php-fpm-configuration&quot;&gt;Php-fpm configuration&lt;/h2&gt;

&lt;p&gt;Edit Php-fpm configuration file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/php-fpm.d/www.conf

user = nginx
group = nginx

listen = 127.0.0.1:9000

env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next, create a new directory for the session path in the &lt;em&gt;/var/lib/&lt;/em&gt; directory, and change the owner to the &lt;em&gt;nginx&lt;/em&gt; user:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /var/lib/php/session&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# chown nginx:nginx -R /var/lib/php/session/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Launch &lt;em&gt;nginx&lt;/em&gt; and &lt;em&gt;php-fpm&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# php-fpm&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl status php-fpm&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable php-fpm&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl start php-fpm&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl status nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl start nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There existed an error when starting &lt;em&gt;php-fpm&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Aug 05 05:52:29 localhost php-fpm[7613]: [05-Aug-2017 05:52:29] NOTICE: PHP message: PHP Fatal error:  PHP Startup: apc_shm_create: shmget(0, 67108864, 914) failed: Invalid argument. It is possible that the chosen SHM segment size is higher than the operation system allows. Linux has usually a default limit of 32MB per segment. in Unknown on line 0
Aug 05 05:52:29 localhost php-fpm[7613]: [05-Aug-2017 05:52:29] NOTICE: PHP message: PHP Fatal error:  PHP Startup: apc_shm_attach: shmat failed: in Unknown on line 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That was caused by &lt;em&gt;shm&lt;/em&gt; size (32M) of CentOS 7 kernel much smaller than that (64M) of Php APC user cache (APCu) setting. Kernel&apos;s &lt;em&gt;shm&lt;/em&gt; value can be verified by&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# sysctl -a | grep -i shm&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kernel.shmmax = 33554432&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kernel.shmall = 2097152&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# kernel.shmmni = 4096&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cat /proc/sys/kernel/shmmax&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The upper bond here is 33554432 Bytes (32M). However, the value of APCu &lt;em&gt;shm&lt;/em&gt; size is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/php.d/apcu.ini
# The size of each shared memory segment with M/G suffix.
apc.shm_size=64M
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So we can either cut down APCu &lt;em&gt;shm&lt;/em&gt; size or increase that of kernel:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# sysctl -w kernel.shmmax=67108864&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# To be permanent across reboot:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vi /etc/sysctl.d/15-shmmax.conf&lt;/span&gt;
kernel.shmmax &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 67108864
~ &lt;span class=&quot;c&quot;&gt;# sysctl -f /etc/sysctl.d/15-shmmax.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;install-nextcloud-tarball&quot;&gt;Install Nextcloud tarball&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# wget https://download.nextcloud.com/server/releases/nextcloud-12.0.1.tar.bz2&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum install bzip2&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# tar -xjpvf nextcloud-12.0.1.tar.bz2 -C /usr/share/nginx/html/&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# chown nginx:nginx -R /usr/share/nginx/html/nextcloud/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Create &lt;em&gt;data&lt;/em&gt; folder of Nextcloud &lt;em&gt;outside&lt;/em&gt; of web root:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /opt/nextcloud-data&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# chown nginx:nginx -R /opt/nextcloud-data/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;nginx-configuration-for-nextcloud&quot;&gt;Nginx configuration for Nextcloud&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# cd /etc/nginx/conf.d/&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# vim nextcloud.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://docs.nextcloud.com/server/12/admin_manual/installation/nginx.html&quot;&gt;Nginx Configuration&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Check &lt;em&gt;server_name&lt;/em&gt;, &lt;em&gt;root&lt;/em&gt;, &lt;em&gt;ssl_certificate&lt;/em&gt; and &lt;em&gt;ssl_certificate_key&lt;/em&gt; etc. directives.&lt;/li&gt;
  &lt;li&gt;If the host posesses IPv6 address, add directives &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen [::]:80;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen [::]:443 ssl http2;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/nginx/conf.d/nextcloud.conf

upstream php-handler {
    server 127.0.0.1:9000;
    #server unix:/var/run/php5-fpm.sock;
}

server {
    listen 80;
    listen [::]:80;
    server_name cloud.example.com;
    # enforce https
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name cloud.example.com;

    ssl_certificate &quot;/etc/letsencrypt/live/cloud.example.com/fullchain.pem&quot;;
    ssl_certificate_key &quot;/etc/letsencrypt/live/cloud.example.com/privkey.pem&quot;;

    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    # add_header Strict-Transport-Security &quot;max-age=15768000;
    # includeSubDomains; preload;&quot;;
    #
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection &quot;1; mode=block&quot;;
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;

    # Path to the root of your installation
    root /usr/share/nginx/html/nextcloud/;

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # The following 2 rules are only needed for the user_webfinger app.
    # Uncomment it if you&apos;re planning to use this app.
    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json
    # last;

    location = /.well-known/carddav {
      return 301 $scheme://$host/remote.php/dav;
    }
    location = /.well-known/caldav {
      return 301 $scheme://$host/remote.php/dav;
    }

    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    # Uncomment if your server is build with the ngx_pagespeed module
    # This module is currently not supported.
    #pagespeed off;

    location / {
        rewrite ^ /index.php$uri;
    }

    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)/ {
        deny all;
    }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) {
        deny all;
    }

    location ~ ^/(?:index|remote|public|cron|core/ajax/update|status|ocs/v[12]|updater/.+|ocs-provider/.+)\.php(?:$|/) {
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        #Avoid sending the security headers twice
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ ^/(?:updater|ocs-provider)(?:$|/) {
        try_files $uri/ =404;
        index index.php;
    }

    # Adding the cache control header for js and css files
    # Make sure it is BELOW the PHP block
    location ~ \.(?:css|js|woff|svg|gif)$ {
        try_files $uri /index.php$uri$is_args$args;
        add_header Cache-Control &quot;public, max-age=15778463&quot;;
        # Add headers to serve security related headers (It is intended to
        # have those duplicated to the ones above)
        # Before enabling Strict-Transport-Security headers please read into
        # this topic first.
        # add_header Strict-Transport-Security &quot;max-age=15768000;
        #  includeSubDomains; preload;&quot;;
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the domain to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection &quot;1; mode=block&quot;;
        add_header X-Robots-Tag none;
        add_header X-Download-Options noopen;
        add_header X-Permitted-Cross-Domain-Policies none;
        # Optional: Don&apos;t log access to assets
        access_log off;
    }

    location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
        try_files $uri /index.php$uri$is_args$args;
        # Optional: Don&apos;t log access to other assets
        access_log off;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;lets-encrypt-certificate&quot;&gt;&lt;a href=&quot;/2017/10/10/le-certificate&quot;&gt;Let&apos;s Encrypt Certificate&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;We should has SSL certificate to domain &lt;em&gt;cloud.example.com&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# certbot certonly --cert-name cloud.example.com --webroot -w /usr/share/nginx/html/ -d cloud.example.com --dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;launch-nextcloud&quot;&gt;Launch Nextcloud&lt;/h2&gt;

&lt;p&gt;After uploading the configuration to &lt;em&gt;/etc/nginx/conf.d/nextcloud.conf&lt;/em&gt;, check syntax and reload &lt;em&gt;nginx&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# nginx -t&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl reload nginx&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# nginx -s reload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;enhancements&quot;&gt;Enhancements&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nextcloud supports loading configuration parameters from multiple files. You can add arbitrary files ending with &lt;em&gt;*.config.php&lt;/em&gt; in the &lt;em&gt;config/&lt;/em&gt; directory, for example you could place your email server configuration in &lt;em&gt;email.config.php&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;During configuration, some variables deserve special attention: Php &lt;em&gt;memory_limit&lt;/em&gt;, APCu &lt;em&gt;shm&lt;/em&gt; size, etc.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Reset admin password.&lt;/p&gt;

    &lt;p&gt;Nextcloud installation wizard does not ask for password confirmation. If you cannot remember the correct password, please &lt;a href=&quot;https://docs.nextcloud.com/server/12/admin_manual/configuration_user/reset_user_password.html&quot;&gt;reset it&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php /usr/share/nginx/html/nextcloud/occ user:resetpassword admin-bob&quot; nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://docs.nextcloud.com/server/12/admin_manual/configuration_server/harden_server.html#use-https&quot;&gt;HTTP Strict Transport Security - HSTS&lt;/a&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/nginx/conf.d/nextcloud.conf
# https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
add_header Strict-Transport-Security &quot;max-age=15768000; includeSubDomains; preload;&quot; always;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;OPcache&lt;/p&gt;

    &lt;p&gt;On the admin panel, you might recived message:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;The PHP Opcache is not properly configured. For better performance we recommend ↗ to use following settings in the php.ini&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;First make sure Php &lt;em&gt;opcache&lt;/em&gt; module is installed by:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# php -m | grep -i opcache&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum install php70w-opcache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Then update &lt;em&gt;/etc/php.d/opcache.ini&lt;/em&gt; as instructed:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/php.d/opcache.ini
   
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Updates to Php &lt;em&gt;*.ini&lt;/em&gt; configuration file require reloading &lt;em&gt;php-fpm&lt;/em&gt; service.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Php memory limit&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory_limit&lt;/code&gt; in default &lt;em&gt;/etc/php.ini&lt;/em&gt; is 128M. However per-site value of Nextcloud in &lt;em&gt;.user.ini&lt;/em&gt; is 512M that is the whole available amount. To prevent Php from exhausting too much memory, set to 128M instead.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /usr/share/nginx/html/nextcloud/.user.ini
upload_max_filesize=100M
post_max_size=100M
memory_limit=128M
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Per-site Php setting overrides that of global under &lt;em&gt;/etc&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;It does not require &lt;em&gt;php-fpm&lt;/em&gt; reloading.&lt;/li&gt;
      &lt;li&gt;Make sure &lt;em&gt;upload_max_filesize&lt;/em&gt; and &lt;em&gt;post_max_size&lt;/em&gt; value is smaller than &lt;em&gt;memory_limit&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Local user (APCu) and Distributed cache (Redis)&lt;/p&gt;

    &lt;p&gt;Php APCu module is installed previously, then enable it in &lt;em&gt;config.php&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /usr/share/nginx/html/nextcloud/config/personal.config.php
&apos;memcache.local&apos; =&amp;gt; &apos;\OC\Memcache\APCu&apos;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Updates to &lt;em&gt;*.php&lt;/em&gt; requires NO service reloading (just refreshing web page) except installing new Php modules.&lt;/li&gt;
      &lt;li&gt;As I use nextcloud for private useage, &lt;em&gt;distributed&lt;/em&gt; cache (Memcache/Redis) is not a must.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Redis as file locking backend&lt;/p&gt;

    &lt;p&gt;Though Redis as distributed cache is not a must, however Redis cache can also act as Transactional File Locking backend. File locking is enabled by default, using the database locking backend. This places a significant load on your database.&lt;/p&gt;

    &lt;p&gt;Using memcache.locking relieves the database load and improves performance.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum install redis php70w-pecl-redis&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl status redis&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable redis&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl start redis&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Add the following to &lt;em&gt;config.php&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /usr/share/nginx/html/nextcloud/config/personal.config.php

&apos;filelocking.enabled&apos; =&amp;gt; true,
&apos;memcache.locking&apos; =&amp;gt; &apos;\OC\Memcache\Redis&apos;,
&apos;redis&apos; =&amp;gt; [
  &apos;host&apos; =&amp;gt; &apos;localhost&apos;, // can also be a unix domain socket: &apos;/tmp/redis.sock&apos;
  &apos;port&apos; =&amp;gt; 6379,
  &apos;timeout&apos; =&amp;gt; 0.0,
  &apos;password&apos; =&amp;gt; &apos;dunno&apos;, // Optional, if not defined no password will be used.
  &apos;dbindex&apos; =&amp;gt; 0, // Optional, if undefined SELECT will not run and will use Redis Server&apos;s default DB Index.
],
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;For enhanced security, please set a password for Redis cache. Reload &lt;em&gt;php-fpm&lt;/em&gt; and refresh web page.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Disable thumbnailer.&lt;/p&gt;

    &lt;p&gt;By default, thumbnailer is enabled for images, mp3, etc., which however impacts overhead on system resources. Without previews, Nextcloud runs fairly smoothly.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /usr/share/nginx/html/nextcloud/config/personal.config.php

&apos;enable_previews&apos; =&amp;gt; false,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The &lt;a href=&quot;https://github.com/nextcloud/server/issues/6000&quot;&gt;side effect&lt;/a&gt; of disabling previews is Gallery app no longer show any media files:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;No media files found&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Why not disable Gallery as well?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Email notification.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;TLS (STARTTLS) with 587, SSL (SSL/TLS) with 465.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /usr/share/nginx/html/nextcloud/config/personal.config.php

&quot;mail_smtpmode&quot; =&amp;gt; &quot;smtp&quot;,
&quot;mail_smtpsecure&quot; =&amp;gt; &apos;tls&apos;,
&quot;mail_smtpport&quot; =&amp;gt; 587,
&quot;mail_smtphost&quot; =&amp;gt; &quot;smtp-mail.outlook.com&quot;,
&quot;mail_domain&quot; =&amp;gt; &quot;outlook.com&quot;,
&quot;mail_from_address&quot; =&amp;gt; &quot;valid-alias&quot;,
&quot;mail_smtpauth&quot; =&amp;gt; true,
&quot;mail_smtpauthtype&quot; =&amp;gt; &quot;LOGIN&quot;,
&quot;mail_smtpname&quot; =&amp;gt; &quot;email@outlook.com&quot;,
&quot;mail_smtppassword&quot; =&amp;gt; &quot;email-password&quot;,
&quot;mail_smtptimeout&quot; =&amp;gt; 30,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Outlook only accept valid &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mail_from_address&lt;/code&gt; owned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mail_smtpname&lt;/code&gt;. Fake &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mail_from_address&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mail_domain&lt;/code&gt; cannot authenticate to the Outlook SMTP server.&lt;/li&gt;
      &lt;li&gt;If a malware or SPAM scanner is running on the SMTP server it might be necessary that you increase the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mail_smtptimeout&lt;/code&gt; value.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;4-byte-utf-8-support&quot;&gt;&lt;a href=&quot;https://docs.nextcloud.com/server/12/admin_manual/configuration_database/mysql_4byte_support.html&quot;&gt;4-byte UTF-8 support&lt;/a&gt;&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Read &lt;a href=&quot;https://github.com/nextcloud/documentation/issues/513&quot;&gt;No FILE_FORMAT&lt;/a&gt; and &lt;strong&gt;backup&lt;/strong&gt; database before going on!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;maintenance mode&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php ./occ maintenance:mode --on&quot; nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;InnoDB&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/etc/my.cnf.d/4-byte.cnf
[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
innodb_large_prefix = 1
innodb_file_format = barracuda
innodb_file_per_table = 1
character-set-client-handshake = 0
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Restart Mariadb&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# systemctl restart mariadb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;4-byte UTF-8&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ # mysql -u nc_db -pPassword
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/a/9531221&quot;&gt;Modify database&lt;/a&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ALTER DATABASE nc_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
use nc_db;
# For each table in nc_db:
ALTER TABLE &amp;lt;table_name&amp;gt; CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# For each column in &amp;lt;table_name&amp;gt;:
ALTER TABLE &amp;lt;table_name&amp;gt; MODIFY &amp;lt;column_name&amp;gt; VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;mysql.utf8mb4&lt;/em&gt; in &lt;em&gt;config.php&lt;/em&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;su -s /bin/bash -c &quot;php ./occ config:system:set mysql.utf8mb4 --type boolean --value=true&quot; nginx
su -s /bin/bash -c &quot;php ./occ maintenance:mode --off&quot; nginx
su -s /bin/bash -c &quot;php ./occ maintenance:repair&quot; nginx
su -s /bin/bash -c &quot;php ./occ maintenance:mode --on&quot; nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Attention: turn off &lt;em&gt;maintenace&lt;/em&gt; mode before &lt;em&gt;repair&lt;/em&gt; since it requires apps be loaded.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;data-folder&quot;&gt;Data folder&lt;/h2&gt;

&lt;p&gt;The previous setup use a separate data directory &lt;em&gt;/opt/nextcloud-data&lt;/em&gt; for files. If you&apos;d like to switch to another location (i.e. &lt;em&gt;/usr/local/data&lt;/em&gt;), use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;php ./occ files:scan --all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Firstly, move data folder to the new location:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mv /opt/nextcloud-data /usr/local/data&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# chown -R nginx:nginx /usr/local/data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Afterwards, tell Nextcloud where the new location is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# vi /usr/share/nginx/html/nextcloud/config/personal.config.php
&apos;datadirectory&apos; =&amp;gt; &apos;/usr/local/data&apos;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, refresh Nextcloud by &lt;em&gt;occ&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php ./occ files:scan --all&quot; nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt;: with the help of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occ files:scan --all&lt;/code&gt;, we can modify (add, remove files) data directory directly without the interfence of Nextcloud web or clients. For example, you have a big video file on server, and have to fetch the video file to local PC and then synchronize through Nextcloud client. Alternatively, just copy the video file to &lt;em&gt;/opt/nextcloud-data/username/files/Documents&lt;/em&gt; and run the &lt;em&gt;occ&lt;/em&gt; command above.&lt;/p&gt;

&lt;h1 id=&quot;dav&quot;&gt;DAV&lt;/h1&gt;

&lt;h2 id=&quot;carddav&quot;&gt;CardDAV&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;App Contacts 1.5.3 by default does not create default address-book upon installation. Before creating or importing any contacts, an address-book must be created at first.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/nextcloud/contacts/issues/235&quot;&gt;Importing address book from file works only partially because import breaks process limit in shared hosting environment&lt;/a&gt;.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Contact could not be created.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Further checking web server log, I found this:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;10 worker_connections are not enough while connecting to upstream, client: 192.168.0.100, server: cloud.example.com, request: &quot;PUT /remote.php/dav/addressbooks/users/jim/test-50/12345678-f873-4f3b-861d-6a6b5b78e5a5.vcf HTTP/1.1&quot;, upstream: &quot;fastcgi://127.0.0.1:9999&quot;, host: &quot;cloud.example.com&quot;&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;ol&gt;
      &lt;li&gt;If you have a big contacts &lt;em&gt;vcard&lt;/em&gt; file to be imported, cut it into smaller blocks (i.e. every 100 contacts) and import one by one.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Increase web server&apos;s allowed concurrent connections, take Nginx for example:&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/nginx/nginx.conf

events {
worker_connections 1024;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;Set back to original value once imported.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/nextcloud/server/issues/3084&quot;&gt;contact birthdays with no year given are shown with (*1604) in calendar&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;The contacts app is using VCARD 3.0 at the moment.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;caldva&quot;&gt;CalDVA&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Calendar app may remind incompatible &lt;em&gt;ics&lt;/em&gt; format, then import without specifying an existing calendar and use &lt;em&gt;New Calendar&lt;/em&gt; instead.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add or subscribe to &lt;a href=&quot;https://github.com/infinet/lunar-calendar&quot;&gt;中国农历&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Currently (as of Nextcloud 12), subscribed &lt;em&gt;iCal&lt;/em&gt; web link &lt;a href=&quot;https://github.com/nextcloud/server/issues/1497&quot;&gt;would not&lt;/a&gt; be synced to mobile (i.e. Davdroid).&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Use &lt;a href=&quot;https://davdroid.bitfire.at/faq/entry/subscribe-ics-file/&quot;&gt;ICSdroid&lt;/a&gt; to subscribe the original link or to Nextcloud&apos;s subscription link.&lt;/li&gt;
      &lt;li&gt;As &lt;a href=&quot;https://github.com/infinet/lunar-calendar&quot;&gt;中国农历&lt;/a&gt; writes, use the tool to generate lunar for incoming years, which won&apos;t consume too much disk space. Afterwards, import that as a new calendar instead of a subscription.&lt;/li&gt;
      &lt;li&gt;Wait for Nextcloud 14.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Obviously, the 2nd method is favorable.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;davdroid--etar&quot;&gt;DAVDroid / Etar&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;When adding Davdroid account, select,&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Contact group method: groups are per-contact categories&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;as Nextcloud Contact app does &lt;em&gt;not&lt;/em&gt; support VCARD 4.0.&lt;/p&gt;

    &lt;p&gt;This is &lt;strong&gt;NOT&lt;/strong&gt; true when DAVDroid upgrades to &lt;em&gt;1.11.4.1-ose&lt;/em&gt; and choose,&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Groups are separate VCards&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://forums.bitfire.at/topic/1508/zte-nubia-requires-autostart&quot;&gt;Davdroid does not sync at all&lt;/a&gt;. For synchronization, must turn on &lt;a href=&quot;https://davdroid.bitfire.at/faq/entry/miui-no-synchronization/&quot;&gt;&lt;em&gt;autostart&lt;/em&gt;&lt;/a&gt; for Davdroid in system setting.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If Davdroid address book or calendar does not show up stock Contacts/Calendar apps, try &lt;em&gt;True Contacts&lt;/em&gt; and &lt;em&gt;Etar&lt;/em&gt; instead.&lt;/p&gt;

    &lt;p&gt;Etar has, by default, a special calendar called &apos;Contact Birthday nobody@gmail.com&apos; which show &lt;em&gt;local&lt;/em&gt; contacts&apos; birthday. &lt;em&gt;*Please&lt;/em&gt; disable it&apos;s synchronization under &apos;CALENDARS TO SYNC&apos;, otherwise it incurs duplicate birthday events.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;maintenance&quot;&gt;Maintenance&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;su &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /bin/bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;php ./occ dav:sync-birthday-calendar&quot;&lt;/span&gt; nginx
   ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;su &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /bin/bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;php ./occ dav:sync-system-addressbook&quot;&lt;/span&gt; nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For example, you accidently delete the default &apos;Contact birthdays&apos; subscription, the first command will get it back.&lt;/p&gt;

&lt;h1 id=&quot;notes-1&quot;&gt;Notes&lt;/h1&gt;

&lt;p&gt;Evernote has now gone too far, leaving its users behind. I want to just abandon it. But by far, neither &lt;a href=&quot;https://apps.nextcloud.com/apps/notes&quot;&gt;Nextcloud official Notes app&lt;/a&gt; (I use this one) nor &lt;a href=&quot;https://github.com/janis91/nextnotes&quot;&gt;unofficial Nextnotes&lt;/a&gt; support importing Evernote notes.&lt;/p&gt;

&lt;p&gt;However, we have &lt;a href=&quot;https://github.com/pbek/QOwnNotes&quot;&gt;QOwnNotes&lt;/a&gt; as provisional tool to transmitting Evernotes to Nextloud.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install QOwnNotes and Nextcloud on your system.&lt;/li&gt;
  &lt;li&gt;Install and enable &lt;a href=&quot;https://github.com/pbek/qownnotesapi&quot;&gt;QOwnNotesAPI&lt;/a&gt; (optional)&lt;/li&gt;
  &lt;li&gt;Add Nextcloud account to QOwnNotes client. (optional)&lt;/li&gt;
  &lt;li&gt;IMPORTANT! Set QOwnNotes &lt;em&gt;note folder path&lt;/em&gt; to be that of Nextcloud.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.qownnotes.org/Blog/Evernote-import&quot;&gt;Export Evernote&lt;/a&gt; notebook to ENEX format &lt;em&gt;.enex&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Import the &lt;em&gt;.enex&lt;/em&gt; in QOwnNotes.&lt;/li&gt;
  &lt;li&gt;Sync the notes in Nextcloud client.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;The 2nd and 3rd steps are unneccessary since we won&apos;t use QOwnNotes after the transmission. Pay attention to the &lt;a href=&quot;http://www.qownnotes.org/Knowledge-base/Why-isn-t-QOwnNotesAPI-syncing-my-notes&quot;&gt;role of QOwnNotesAPI&lt;/a&gt;. Normal note files are handled by Nextloud while note transhes and versions (on the server side) are handled by QOwnNotesAPI separately.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;bug&quot;&gt;Bug&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/nextcloud/notes/issues/133&quot;&gt;A bug of Notes app in web interface&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, the first line of a note will be the filename. Maybe, the Notes app in web interface cannot create the right file name with full shape punctuators or Chinese characters.&lt;/p&gt;

&lt;p&gt;The current solution is to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Disable Notes app;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Backup and remove the Files - Notes folder;&lt;/p&gt;

    &lt;p&gt;Specifically remove the &lt;em&gt;troublesome&lt;/em&gt; new note file.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Re-enable Notes app;&lt;/li&gt;
  &lt;li&gt;Apply &lt;a href=&quot;https://github.com/nextcloud/notes/pull/125&quot;&gt;No. 125&lt;/a&gt; patch.&lt;/li&gt;
  &lt;li&gt;Move back the Notes folder&lt;/li&gt;
  &lt;li&gt;Do a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occ files:scan --all&lt;/code&gt; and reload Notes app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To further fix broken activity app, we should remove the troublesome activity records:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mysql -u nc_db -pPassword
select activity_id,type,app,subject,subjectparams,file,link from nc_db.oc_activity order by activity_id DESC limit 10;
delete from nextcloud.oc_activity where activity_id&amp;gt;2300;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adjust the &lt;em&gt;activity_id&lt;/em&gt; range.&lt;/p&gt;

&lt;h1 id=&quot;news&quot;&gt;News&lt;/h1&gt;

&lt;p&gt;After enabling News app, you receives warnings like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ajax or Web cron mode detected! Your feeds will not updated!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By default, &lt;a href=&quot;https://docs.nextcloud.com/server/12/admin_manual/configuration_server/background_jobs_configuration.html&quot;&gt;Nexcloud Ajax&lt;/a&gt; is used. For news to be updated automatically, we should use system cron service. If you don&apos;t care about automatic news fetch, just ignore that.&lt;/p&gt;

&lt;p&gt;Firstly, install &lt;em&gt;cronie&lt;/em&gt; service:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum install cronie&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable crond&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl start crond&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cat /etc/crontab&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, we add cron job for user &lt;em&gt;nginx&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# crontab -u nginx -e&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;/15  &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; php &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; /var/www/nextcloud/cron.php
~ &lt;span class=&quot;c&quot;&gt;# crontab -u nginx -l&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cat /var/spool/cron/nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, select the option Cron in the admin menu for background jobs. If left on AJAX it would execute the AJAX job on every page load.&lt;/p&gt;

&lt;p&gt;As the reference pointed out, we can use &lt;em&gt;systemd timer&lt;/em&gt; as well. It&apos;s all your choice.&lt;/p&gt;

&lt;h2 id=&quot;tips&quot;&gt;Tips&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;The Android app requires &lt;em&gt;autostart&lt;/em&gt; and &lt;em&gt;storage&lt;/em&gt; permissions to sync feeds.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;backup&quot;&gt;&lt;a href=&quot;https://docs.nextcloud.com/server/12/admin_manual/maintenance/backup.html&quot;&gt;Backup&lt;/a&gt;&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;Do it before upgrading.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mainly, we should backup &lt;em&gt;folders&lt;/em&gt; and &lt;em&gt;database&lt;/em&gt;.&lt;/p&gt;

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

&lt;ol&gt;
  &lt;li&gt;The config folder, i.e. &lt;em&gt;config.php&lt;/em&gt;, &lt;em&gt;personal.config.php&lt;/em&gt; etc.&lt;/li&gt;
  &lt;li&gt;The data folder. The most important part.&lt;/li&gt;
  &lt;li&gt;The theme folder.&lt;/li&gt;
  &lt;li&gt;During upgrading, the Nextcloud installation folder is backed up automatically. If you trust it, that&apos;s fine.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rsync -avzP --delete nextcloud/ nextcloud-dirbkp_`date +&quot;%Y%m%d&quot;`/ &lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rsync -avzP --delete nextcloud-data/ nextcloud-data-dirbkp_`date +&quot;%Y%m%d&quot;`/ &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Optionally, we can synchroize data to PC just in case.&lt;/p&gt;

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

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# backup
mysqldump --single-transaction -h localhost -u nc_user -pPassword nc_db &amp;gt; nextcloud-sqlbkp_`date +&quot;%Y%m%d&quot;`.bak
# restore
drop database nc_db
create database nc_db
# -or-
create database nc_db default character set utf8mb4 collate utf8mb4_unicode_ci&quot;;
~ # mysql -h localhost -u nc_user -pPassword nc_db &amp;lt; nextcloud-sqlbkp.bak
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There is no space between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt; and Password.&lt;/p&gt;

&lt;h1 id=&quot;update&quot;&gt;&lt;a href=&quot;https://docs.nextcloud.com/server/12/admin_manual/maintenance/update.html&quot;&gt;Update&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Firstly, &lt;em&gt;updater&lt;/em&gt; checks environment.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;updater&lt;/em&gt; enables &lt;em&gt;maintenance&lt;/em&gt; mode automatically.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Secondly, &lt;em&gt;upgrade&lt;/em&gt; does the real update.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Both tools could be executed through the web interface and/or command line.&lt;/p&gt;

    &lt;p&gt;Web-based &lt;em&gt;updater&lt;/em&gt; would ask you if &lt;em&gt;Keep maintenance mode active&lt;/em&gt;. Command line &lt;em&gt;upgrade&lt;/em&gt; and web-based &lt;em&gt;upgrade&lt;/em&gt; require &lt;em&gt;active&lt;/em&gt; (enabled) and &lt;em&gt;inactive&lt;/em&gt; (disabled) maintenance mode respectively.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;We may execute &lt;em&gt;upgrade&lt;/em&gt; twice: one for Nextcloud itself and the other for apps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here, I use command line for the whole update process.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ # cd /usr/share/nginx/html/nextcloud/
~ # su -s /bin/bash -c &apos;php ./updater/updater.phar&apos; nginx
# if errors like &quot;The following extra files have been found: .user.ini.bak&quot;, remove those files. Re-run:
~ # su -s /bin/bash -c &apos;php ./updater/updater.phar&apos; nginx
# Should the &quot;occ upgrade&quot; command be executed? [Y/n] Y
# Keep maintenance mode active? [y/N] N
~ # su -s /bin/bash -c &apos;php occ status&apos; nginx
~ # su -s /bin/bash -c &apos;php occ upgrade&apos; nginx (optionally)
~ # su -s /bin/bash -c &apos;php ./updater/updater.phar&apos; nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please execute &lt;em&gt;occ upgrade&lt;/em&gt; when prompted by &lt;em&gt;occ status&lt;/em&gt;, which is usually required when new app versions are available.&lt;/p&gt;

&lt;h2 id=&quot;miantenance-mode&quot;&gt;miantenance mode&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;maintenance:mode&lt;/em&gt; locks the sessions of logged-in users and prevents new logins. This is the mode to use for upgrades. Check the mode by:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# &quot;maintenance&quot; value in &apos;config.php&apos; is updated accordingly&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php ./occ list&quot; nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php ./occ maintenance:mode&quot; nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php ./occ maintenance:mode --on/off &quot; nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;domain-switch&quot;&gt;Domain switch&lt;/h1&gt;

&lt;p&gt;Suppose you would moving from &lt;em&gt;cloud.old.com&lt;/em&gt; to &lt;em&gt;cloud.new.com&lt;/em&gt;, then remember to modify &lt;em&gt;trusted_domains&lt;/em&gt; and &lt;em&gt;overwrite.cli.url&lt;/em&gt; in &lt;em&gt;config/config.php&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   &apos;trusted_domains&apos; =&amp;gt;
   array (
     0 =&amp;gt; &apos;192.168.0.29&apos;,
     1 =&amp;gt; &apos;cloud.new.com&apos;,
   ),
   &apos;overwrite.cli.url&apos; =&amp;gt; &apos;https://cloud.new.com&apos;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This can be done by &lt;em&gt;occ&lt;/em&gt; as well:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php ./occ config:system:get trusted_domains&quot; nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php ./occ config:system:set trusted_domains 1 --value=cloud.new.com&quot; nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php ./occ config:system:get overwrite.cli.url&quot; nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# su -s /bin/bash -c &quot;php ./occ config:system:set overwrite.cli.url --value=https://cloud.new.com&quot; nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.howtoforge.com/tutorial/how-to-install-nextcloud-with-nginx-and-php-fpm-on-centos-7/&quot;&gt;How to Install Nextcloud with Nginx and PHP7-FPM on CentOS 7&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.orgleaf.com/2504.html&quot;&gt;在CentOS7上使用Nginx和PHP7-FPM安装Nextcloud&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.marksei.com/install-nextcloud-12-centos-7/&quot;&gt;How to install Nextcloud 12 server on CentOS 7&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nifume.com/build_nextcloud_service_on_centos_with_selinux.html&quot;&gt;启用 SELinux 的情况下，在 CentOS 上搭建 NextCloud/ownCloud 服务&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/terrylinooo/daily/wiki/Install-Nginx,-PHP-7,-MariaDB-10-(LEMP)-on-CentOS-7&quot;&gt;Install Nginx, PHP 7, MariaDB 10 (LEMP) on CentOS 7&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>simple-obfs</title>
   <link href="/2017/05/07/simple-obfs/"/>
   <updated>2017-05-07T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/05/07/simple-obfs</id>
   <content type="html">&lt;h1 id=&quot;abc&quot;&gt;ABC&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;As &lt;a href=&quot;/2016/04/12/ptproxy/&quot;&gt;ptproxy&lt;/a&gt; is almost dead and shadowsocks advances further, we require a newer traffic obfuscation tool, where &lt;a href=&quot;https://github.com/shadowsocks/simple-obfs&quot;&gt;simple-obfs&lt;/a&gt; comes to sight.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;simple-obfs&lt;/em&gt; is similar to Tor Pluggable Transport (i.e. obfs4proxy) in disguising abnormal traffic as daily HTTP(s), thus free from firewall interference.&lt;/li&gt;
  &lt;li&gt;This post prefers &lt;em&gt;standalone&lt;/em&gt; mode.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The author does not provide information on configuration file format.&lt;/p&gt;

    &lt;p&gt;Please check &lt;em&gt;jconf_t * read_jconf (const char *file)&lt;/em&gt; function within &lt;em&gt;src/jconf.c&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;build&quot;&gt;Build&lt;/h1&gt;

&lt;p&gt;I will show how to build binary in Gentoo. Before that, make sure dependency packages are installed.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/opt/
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 https://github.com/shadowsocks/simple-obfs
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;simple-obfs/
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git submodule update &lt;span class=&quot;nt&quot;&gt;--init&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--recursive&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./autogen.sh
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./configure &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/home/username/opt] &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; make
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/opt
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cp src/{obfs-local,obfs-server} /opt/bin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;By default, binaries, doc, man are installed into &lt;em&gt;/usr/local/{bin,doc,man}&lt;/em&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configure --prefix=/foo/bar&lt;/code&gt; changes to &lt;em&gt;/foo/bar&lt;/em&gt;.
    &lt;ol&gt;
      &lt;li&gt;Do not put tailing slash to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--prefix=&lt;/code&gt; argument.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;prefix&lt;/em&gt; must be &lt;em&gt;absolute&lt;/em&gt; path.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;To be simple, &lt;em&gt;obfs-local&lt;/em&gt; and &lt;em&gt;obfs-server&lt;/em&gt; binaries are enough. Just copy to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, to clean letfovers:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/opt/simple-obfs
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make clean
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;make distclean
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;server-unit&quot;&gt;Server unit&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Unit]
Description=simple-obfs server
Requires=shadowsocks-libev.service
After=network.target shadowsocks-libev.service

[Service]
Type=simple
PermissionsStartOnly=false
User=nobody
Group=nobody
LimitNOFILE=4096
ExecStart=/usr/local/bin/obfs-server -c /etc/shadowsocks-libev/obfs-server.json

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;server-json&quot;&gt;Server json&lt;/h2&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0.0.0.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1235&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;dst_addr&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1:1236&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;timeout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;obfs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;tls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;failover&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;www.bing.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fast_open&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Listen on port 1235 for &lt;em&gt;obfs-client&lt;/em&gt; connection;&lt;/li&gt;
  &lt;li&gt;Forward traffic to &lt;em&gt;shadowsocks&lt;/em&gt; on port 1235;&lt;/li&gt;
  &lt;li&gt;Obfuscation method is &lt;em&gt;http&lt;/em&gt; or &lt;em&gt;tls&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Fail over to public domain or personal web server.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;client-initd&quot;&gt;Client initd&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/sbin/openrc-run
#
# &apos;start-stop-daemon&apos; arguments resides before &apos;--exec&apos; while
# &quot;${OBFS_COMMAND}&quot; arguments after two succesive dashes &apos;--&apos;.
#
# Drop to &apos;nobody&apos; user.

USER=&quot;nobody&quot;

OBFS_COMMAND=&quot;/opt/bin/obfs-local&quot;
OBFS_PIDFILE=&quot;/var/run/simple-obfs.pid&quot;
OBFS_CONFILE=&quot;/etc/shadowsocks-libev/obfs-local.json&quot;

depend() {
  after dhcpcd
}

start() {
  if [ &quot;${RC_CMD}&quot; = &quot;restart&quot; ];
  then
    ebegin &quot;Restarting obfs-local&quot;
    eend $?
  fi

  ebegin &quot;Starting obfs-local&quot;

  # start-stop-daemon -S -x &quot;${OBFS_COMMAND}&quot; -u &quot;${USER}&quot; -b -m -p &quot;${OBFS_PIDFILE}&quot; -- -c &quot;${OBFS_CONFILE}&quot;
  start-stop-daemon -S -x &quot;${OBFS_COMMAND}&quot; -- -c &quot;${OBFS_CONFILE}&quot; -a &quot;${USER}&quot; -f &quot;${OBFS_PIDFILE}&quot;

  eend $?
}

stop() {
  ebegin &quot;Stopping obfs-local&quot;

  start-stop-daemon -K -p &quot;${OBFS_PIDFILE}&quot;

  eend $?
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;client-json&quot;&gt;Client json&lt;/h2&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;vps-ip&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1235&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local_address&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1234&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;timeout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;obfs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;tls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;obfs_host&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;www.bing.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fast_open&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Notice that &lt;em&gt;server&lt;/em&gt; and &lt;em&gt;server_port&lt;/em&gt; remain unchanged irrespective of client or server side.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;notes&quot;&gt;Notes&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Make sure Iptables allows relevant ports and IPs.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;On Android, first install &lt;em&gt;simple-obfuscation&lt;/em&gt; app. Afterwards, Change profile port to that of &lt;em&gt;obfs-server&lt;/em&gt;. Obviously, you should set &lt;em&gt;Configure&lt;/em&gt; part to relevant values.&lt;/p&gt;

    &lt;p&gt;You may got &lt;em&gt;&lt;a href=&quot;https://github.com/shadowsocks/shadowsocks-android/issues/1428&quot;&gt;unknown&lt;/a&gt; plugin obfs-local&lt;/em&gt; error after the exact first run. Please turn on &lt;em&gt;autostart&lt;/em&gt; permission.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Nginx</title>
   <link href="/2017/04/11/nginx/"/>
   <updated>2017-04-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/04/11/nginx</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#nginx-installation&quot; id=&quot;markdown-toc-nginx-installation&quot;&gt;Nginx Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#nginx-overview&quot; id=&quot;markdown-toc-nginx-overview&quot;&gt;Nginx Overview&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#control-signal&quot; id=&quot;markdown-toc-control-signal&quot;&gt;Control Signal&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configuration-tips&quot; id=&quot;markdown-toc-configuration-tips&quot;&gt;Configuration Tips&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#if-else&quot; id=&quot;markdown-toc-if-else&quot;&gt;if else&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#number-of-connections&quot; id=&quot;markdown-toc-number-of-connections&quot;&gt;Number of Connections&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#catch-all-virtual-server&quot; id=&quot;markdown-toc-catch-all-virtual-server&quot;&gt;Catch-all Virtual Server&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;nginx-installation&quot;&gt;Nginx Installation&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# dnf install nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl enable nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# systemctl status nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;nginx-overview&quot;&gt;Nginx Overview&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://nginx.org/en/docs/beginners_guide.html&quot;&gt;Starter&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Nginx has one master process and several worker processes.
    &lt;ol&gt;
      &lt;li&gt;The main purpose of master process is to read and evaluate configurations, maintain worker processes, manage TCP connections etc.&lt;/li&gt;
      &lt;li&gt;Worker processes serve client requests. The number of worker processes can be configured and is subject to system resources like number of CPU cores, storage size of HDDs, load pattern etc.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Nginx employs event-based model and OS-dependent mechanisms to efficiently distribute requests among worker processes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;control-signal&quot;&gt;Control Signal&lt;/h1&gt;

&lt;p&gt;Test configuration:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# nginx -t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Start Nginx:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# nginx -p &amp;lt;/path/to/prefix&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can control Nginx with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -s &amp;lt;signal&amp;gt;&lt;/code&gt; option:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;reload - reloading Nginx configuration&lt;/li&gt;
  &lt;li&gt;reopen - log file rotation&lt;/li&gt;
  &lt;li&gt;quit - gracefully shutdown Nginx. Stop only all current requests are served.&lt;/li&gt;
  &lt;li&gt;stop - fast shutdown.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can also &lt;a href=&quot;https://nginx.org/en/docs/control.html&quot;&gt;control&lt;/a&gt; Nginx by sending &lt;em&gt;signal&lt;/em&gt; to the master process directly. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kill -HUP &amp;lt;master-pid&amp;gt;&lt;/code&gt; is an equivalent of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -s reload&lt;/code&gt;. By the way, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl reload nginx&lt;/code&gt; is just a wrapper of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -s reload&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;configuration-tips&quot;&gt;Configuration Tips&lt;/h1&gt;

&lt;p&gt;Do not Repeat Yourself.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Set directives at their broadest applicable context.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Modular configuration. Different configuration files or directories can be integrated into &lt;em&gt;nginx.conf&lt;/em&gt; by the &lt;em&gt;include&lt;/em&gt; directive.&lt;/p&gt;

    &lt;p&gt;Here is the common list of configuration modules.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;sites-available&lt;/li&gt;
      &lt;li&gt;sites-enabled - symbolic links to sites-available&lt;/li&gt;
      &lt;li&gt;default.d&lt;/li&gt;
      &lt;li&gt;modules.d&lt;/li&gt;
      &lt;li&gt;conf.d&lt;/li&gt;
      &lt;li&gt;stream.d&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;if-else&quot;&gt;if else&lt;/h1&gt;

&lt;p&gt;Nginx &lt;em&gt;if&lt;/em&gt; does not support logical AND or OR, so we have to add a particular &lt;em&gt;if&lt;/em&gt; directive for each condition. For logical OR, that is enough. But for logical AND, we also set a variable and then concatenate different flags from those &lt;em&gt;if&lt;/em&gt; directives. Then, a last &lt;em&gt;if&lt;/em&gt; directive is used to check the variable value, as below.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if ($request_uri = /) {
  set $con root;
}

if ($host ~* example.com) {
  set $con &quot;${con}+example.com&quot;;
}

if ($http_cookie !~* &quot;auth_token&quot;) {
  set $con &quot;${con}+no_auth_token&quot;;
}


if ($con = &quot;root+example.com+no_auth_token&quot;) {
  return 403;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;number-of-connections&quot;&gt;Number of Connections&lt;/h1&gt;

&lt;p&gt;By default, a single worker process allows 1024 connections simutaneously. We can litmit the number by:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;events {
    worker_connections 50;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;catch-all-virtual-server&quot;&gt;Catch-all Virtual Server&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# catch-all &apos;default_server&apos; vhosts

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;
    root /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
	    # Use &quot;$host&quot; instead of &quot;$server_name&quot; unless you have special needs.
        #return 301 https://$server_name$request_uri;
        return 301 https://$host$request_uri;
    }
}

# Settings for a TLS enabled server.

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;

    server_name _;
    root /usr/share/nginx/html;

    # Let&apos;s Encrypt will start offer wildcard certs beginning 2018
    ssl_certificate &quot;/etc/letsencrypt/live/example.com/fullchain.pem&quot;;
    ssl_certificate_key &quot;/etc/letsencrypt/live/example.com/privkey.pem&quot;;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
        return 404;
    }

    error_page 404 /40x.html;
    location = /40x.html {
        internal;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        internal;
    }

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

&lt;ol&gt;
  &lt;li&gt;All HTTP requests are redirected (301) to HTTPS.&lt;/li&gt;
  &lt;li&gt;Trigger 404 code, telling end users that the request is not expected.&lt;/li&gt;
  &lt;li&gt;Attention to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server_name: _;&lt;/code&gt;. It is not a must.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Android Linux</title>
   <link href="/2017/04/11/android-linux/"/>
   <updated>2017-04-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/04/11/android-linux</id>
   <content type="html">&lt;h1 id=&quot;outline&quot;&gt;Outline&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Adb&lt;/p&gt;

    &lt;p&gt;PC tool that sends commands to Android system over cable or Wi-Fi. Commands are:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Adb sub-commands like &lt;em&gt;shell&lt;/em&gt;, &lt;em&gt;install&lt;/em&gt;, &lt;em&gt;push&lt;/em&gt;, &lt;em&gt;sideload&lt;/em&gt; etc.&lt;/li&gt;
      &lt;li&gt;Android system commands like &lt;em&gt;pm&lt;/em&gt;, &lt;em&gt;am&lt;/em&gt; etc. by &lt;em&gt;adb shell&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Fastboot&lt;/p&gt;

    &lt;p&gt;Similar to Adb, Fastboot connects to Android bootloader - Fastboot by cable. As Android bootloader does not provide built-in commands, Fastboot supports only sub-commands of itself like &lt;em&gt;flash&lt;/em&gt; etc.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Fastboot tool VS Fastboot bootloader.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;TWRP&lt;/p&gt;

    &lt;p&gt;Android system includes the tiny Recovery and complete Android ROM (i.e. MIUI). TWRP is an extension to stock Recovery with more functionalities. Mostly, we use it to flash 3rd party ROMs.&lt;/p&gt;

    &lt;p&gt;Possible TWRP sub-commands are &lt;em&gt;wipe&lt;/em&gt;, &lt;em&gt;install&lt;/em&gt; etc. by &lt;em&gt;adb shell twrp&lt;/em&gt;.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;You could change TWRP version if flashing failed.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;thunar&quot;&gt;Thunar&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# echo &quot;gnome-base/gvfs mtp&quot; &amp;gt;&amp;gt; /etc/portage/package.use/gvfs&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# emerge -av1 gvfs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Logout and login to take effect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;twrp&quot;&gt;&lt;a href=&quot;https://twrp.me&quot;&gt;TWRP&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rm -rf&lt;/code&gt; to avoid re-formating EXT4 filesystem unpon wiping.&lt;/li&gt;
  &lt;li&gt;After wiping and before flashing, keep all (at least &lt;em&gt;/system&lt;/em&gt;) partitions &lt;em&gt;umount&lt;/em&gt;ed and disable MTP, which otherwise would report &lt;em&gt;system&lt;/em&gt;, &lt;em&gt;data&lt;/em&gt; etc. partitions &lt;em&gt;busy&lt;/em&gt; errors.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Error. If you receive error like:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Unable to mount /data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Resort to:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Adanced Wipe, Repair or Change File System;&lt;/li&gt;
      &lt;li&gt;Reboot TWRP.&lt;/li&gt;
      &lt;li&gt;bootloader emergency recovery wipe;&lt;/li&gt;
      &lt;li&gt;adb sideload.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Instead of flashing TWRP to device, we can temporarily &lt;em&gt;boot&lt;/em&gt; device with TWRP image.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;rom&quot;&gt;ROM&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;If previous ROM is official Android 6.0 and new ROM is 3rd party Android 7.0/7.1, you&apos;d better firstly flash an official 7.0/7.1 development version (a big so-called &quot;底包&quot;).&lt;/li&gt;
  &lt;li&gt;To support F2FS data partition:
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;3rd party recovery (i.e. TWRP) should support creating F2FS filesystem (formating &lt;em&gt;data&lt;/em&gt; and &lt;em&gt;cache&lt;/em&gt; partitions). Don&apos;t format &lt;em&gt;system&lt;/em&gt; partition as F2FS.&lt;/p&gt;

        &lt;p&gt;Formatting &lt;em&gt;data&lt;/em&gt; partition to F2FS would wipe the &lt;em&gt;internal storage&lt;/em&gt; too.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;ROM must run on F2FS systems.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;android-debug-bridge-adb&quot;&gt;&lt;a href=&quot;https://developer.android.com/studio/command-line/adb.html&quot;&gt;Android Debug Bridge&lt;/a&gt; (adb)&lt;/h1&gt;

&lt;p&gt;Android Debug Bridge (adb) is a versatile command-line tool that lets you communicate with a device (an &lt;em&gt;emulator&lt;/em&gt; or a connected Android device).&lt;/p&gt;

&lt;p&gt;The adb command facilitates a variety of device actions, such as installing and debugging apps, and it provides access to a Unix shell that you can use to run a variety of commands on a device.&lt;/p&gt;

&lt;p&gt;It is a client-server program that includes three components:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A client, which sends commands. The client runs on your development machine. You can invoke a client from a command-line terminal by issuing an adb command.&lt;/li&gt;
  &lt;li&gt;A daemon (adbd), which runs commands on an Android device. The daemon runs as a background process on each device.&lt;/li&gt;
  &lt;li&gt;A server, which manages communication between the client and the daemon. The server runs as a background process on your development machine.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;From Gentoo portage:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# emerge -avt dev-util/android-tools&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Android platform tools (adb, fastboot, and mkbootimg)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Logout and login back to take effect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Current stable is 1.0.32. For an up-to-date version (recommended), &lt;a href=&quot;https://developer.android.com/studio/releases/platform-tools.html&quot;&gt;download here&lt;/a&gt;, which is a &lt;em&gt;standalone&lt;/em&gt; version ready for terminal (just extract the zip):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/opt
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;unzip ~/Downloads/platform-tools-latest-linux.zip
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./fastboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;connection-to-device&quot;&gt;Connection to device&lt;/h2&gt;

&lt;p&gt;There are two ways to pair an Android device with your PC, namely over USB cable and over Wi-Fi.&lt;/p&gt;

&lt;p&gt;In order to let computer recognizes the Android device, we should enable:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.android.com/studio/debug/dev-options.html&quot;&gt;Developer options&lt;/a&gt;;&lt;/li&gt;
  &lt;li&gt;USB debugging;&lt;/li&gt;
  &lt;li&gt;Fastboot Unlock (i.e. Xiaomi virgo).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;over-usb-cable&quot;&gt;Over USB cable&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb start-server/kill-server
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb devices &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ss/netstat &lt;span class=&quot;nt&quot;&gt;-npelt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;adb devices&lt;/em&gt; launches &lt;em&gt;adb start-server&lt;/em&gt; on demand. When the server starts, it binds to local TCP port 5037 and listens for commands sent from adb clients - all adb clients use port 5037 to communicate with the adb server.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;adb client - adb server - adb daemon on Android&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example output:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;List of devices attached
afc75758               device usb:1-1.2 product:NX531J model:NX531J device:NX531J
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The serial number is &lt;em&gt;afc75758&lt;/em&gt; while &lt;em&gt;device&lt;/em&gt; represents connection state.&lt;/p&gt;

&lt;p&gt;If &lt;em&gt;adb&lt;/em&gt; prints:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;List of devices attached
afc75758	unauthorized
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unlock your device and confirm PC RSA key (for first connection). This security mechanism protects user devices because it ensures that USB debugging and other adb commands cannot be executed unless you&apos;re able to unlock the device and acknowledge the dialog.&lt;/p&gt;

&lt;p&gt;If &lt;em&gt;adb&lt;/em&gt; complains:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;List of devices attached
afc75758               no permissions (udev requires plugdev group membership); see [http://developer.android.com/tools/device.html] usb:1-1.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Possible methods:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Add current user account into &lt;em&gt;plugdev&lt;/em&gt; group.&lt;/li&gt;
  &lt;li&gt;Run &lt;em&gt;adb&lt;/em&gt; under &lt;em&gt;root&lt;/em&gt; account.&lt;/li&gt;
  &lt;li&gt;Switch the USB connection type from &lt;em&gt;Charge only&lt;/em&gt; to &lt;em&gt;Transmit files&lt;/em&gt; (MTP) or &lt;em&gt;Transmit photos&lt;/em&gt; (PTP) from device drop-down menu. Alternatively, set &lt;em&gt;Select USB configuration&lt;/em&gt; in &lt;em&gt;Developer options&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Follow the given link to create a &lt;strong&gt;udev&lt;/strong&gt; rule your device:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# lsusb
Bus 001 Device 035: ID 19d2:abcd ZTE WCDMA Technologies MSM
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;lsub&lt;/em&gt; prints the device vendor ID (19d2) and product ID (abcd). If &lt;em&gt;/lib/udev/rules.d/69-libmtp.rules&lt;/em&gt; (&lt;em&gt;media-libs/libmtp&lt;/em&gt;) does NOT include your device, then&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/udev/rules.d/51-android.rules
SUBSYSTEM==&quot;usb&quot;, ATTR{idVendor}==&quot;19d2&quot;, ATTRS{idProduct}==&quot;abcd&quot;, GROUP=&quot;plugdev&quot;, MODE=&quot;0660&quot;, SYMLINK+=&quot;NX531J-%k&quot;
# or
SUBSYSTEM==&quot;usb&quot;, ATTRS{idVendor}==&quot;19d2&quot;, ATTRS{idProduct}==&quot;abcd&quot;, OWNER=&quot;jim&quot;, MODE=&quot;0600&quot;, SYMLINK+=&quot;NX531J-%k&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Finally, &lt;em&gt;trigger&lt;/em&gt; the rules:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# gpasswd -a username plugdev (optional)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# udevadm control -R/--reload (optional)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# udevadm trigger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Pay attention to how GROUP and OWNER relates to MODE.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;We might create a new rule for &lt;em&gt;fastboot&lt;/em&gt; (bootloader) uses a different &lt;em&gt;idProduct&lt;/em&gt; number.&lt;/li&gt;
  &lt;li&gt;Different ROM gives differents &lt;em&gt;idProduct&lt;/em&gt; number.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;over-wi-fi&quot;&gt;Over Wi-Fi&lt;/h3&gt;

&lt;p&gt;Connection over Wi-Fi needs some initial setup over USB. Connect your Android device and adb host computer to a common Wi-Fi network accessible to both (i.e. WLAN).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb tcpip 5037
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb connect device_ip_address
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb devices &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Connection over Wi-Fi is slow in speed and less secure subjecting to sniffer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;adb-sub-commands&quot;&gt;adb sub-commands&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;adb &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; | &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; | &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; serial_number] &lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;One of the most special is &lt;em&gt;shell&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb shell
&lt;span class=&quot;c&quot;&gt;# get into Android Linux system&lt;/span&gt;
shell@NX531J:/ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /system/bin
shell@NX531J:/ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;netstat &lt;span class=&quot;nt&quot;&gt;-lt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you are connecting over Wi-Fi, &lt;em&gt;netstat&lt;/em&gt; will show the TCP socket which is owned by &lt;em&gt;adb shell&lt;/em&gt;. To tell the ADB daemon return to listening over USB and closing the socket:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb usb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Other commands are &lt;em&gt;pull/push/backup&lt;/em&gt; for file transmission and backup/restore. Pull/push is pretty fast to transmit files but may the device a hot potato - high temprature.&lt;/p&gt;

&lt;p&gt;You should also pay attention to &lt;em&gt;remount/install/uninstall/shell&lt;/em&gt; for file updating. Apart from traditional shell commands, there are two special ones, namely &lt;strong&gt;am&lt;/strong&gt; (activity manager) and &lt;strong&gt;pm&lt;/strong&gt; (package manager).&lt;/p&gt;

&lt;p&gt;Lastly, the most common command is:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;reboot &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;bootloader|recovery|sideload|sideload-auto-reboot]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As stated in the Outline section, we can use &lt;em&gt;adb shell twrp install /path/to/zip/ROM/on/android&lt;/em&gt; to flash a new ROM.&lt;/p&gt;

&lt;h3 id=&quot;logcat&quot;&gt;logcat&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;logcat&lt;/em&gt; is a pretty useful tool to collect system logs which can be filtered by parameters to focus on specific app.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb shell
shell@NX531J:/ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;logcat &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb logcat &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For example, we want logs of Amaze:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb shell ps | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; amaze
&lt;span class=&quot;c&quot;&gt;# get the PID&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb logcat | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PID&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb logcat &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;:E
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;flashing&quot;&gt;Flashing&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Fastboot is Android device&apos;s bootloader that resembles Grub in loading kernel.
    &lt;ol&gt;
      &lt;li&gt;A system can be a tiny Recovery system or a complete ROM system. That is to say, Recovery and ROM are of equal objects in viewpoint of Fastboot.&lt;/li&gt;
      &lt;li&gt;Device and PC must be connected cable line. This is the reason we call it &quot;线刷&quot; (i.e. fastboot update update.zip). Here is a reference &lt;a href=&quot;http://bbs.xiaomi.cn/t-12560364&quot;&gt;命令行下的fastboot刷机&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Recovery is a tiny runnable Android system. As explained above, we can connect PC to device recovery over cable line or Wi-Fi.&lt;/p&gt;

    &lt;p&gt;Usually Recovery is used to do &quot;卡刷&quot; (PC involvement).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;fastboot&lt;/em&gt; and &lt;em&gt;adb&lt;/em&gt; commands communicate with &lt;em&gt;fastboot&lt;/em&gt; bootloader and &lt;em&gt;recovery/ROM&lt;/em&gt; system respectively.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The ROM (zip) format of &quot;线刷&quot; and &quot;卡刷&quot; is probably different.&lt;/p&gt;

    &lt;p&gt;Check your vendor&apos;s instruction.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;After wiping partitions (data, cache, system, etc.), you&apos;d better reboot TWRP.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;fastboot-twrp&quot;&gt;fastboot TWRP&lt;/h2&gt;

&lt;p&gt;fastboot can flash sparse &lt;em&gt;img&lt;/em&gt; (recovery, data, system, and even self-made ones) to relevant Android partitions. To make fastboot recognize your device,&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Let the device get into fastboot mode.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# get into fastboot mode&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb reboot bootloader
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Another way is to use combination keys mostly by pressing power key and volume down key simultaneously. Details refer to your device documentation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create a udev rule.&lt;/p&gt;

    &lt;p&gt;When the device is at fastboot mode, the product ID changes accordingly. We should add another udev rule like for adb.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;boot/flash&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./fastboot devices &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./fastboot boot recovery /path/to/TWRP.img &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;recommended&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./fastboot &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; 0x19D2 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; flash recovery /path/to/TWRP.img
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;getvar&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./fastboot getvar all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href=&quot;http://c.mi.com/thread-31082-1-1.html&quot;&gt;difference&lt;/a&gt; between &lt;em&gt;flash&lt;/em&gt; and &lt;em&gt;boot&lt;/em&gt; is that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;flash&lt;/em&gt; do flash the TWRP to recovery parition for &lt;em&gt;permanent&lt;/em&gt; effect.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;boot&lt;/em&gt; &lt;em&gt;temporarily&lt;/em&gt; boots the device with TWRP, which resembles a LiveCD environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;adb-sideload-rom&quot;&gt;&lt;a href=&quot;https://twrp.me/faq/ADBSideload.html&quot;&gt;adb sideload&lt;/a&gt; ROM&lt;/h2&gt;

&lt;p&gt;As of version 2.3, TWRP now supports &lt;em&gt;adb sideload&lt;/em&gt; mode. ADB sideload is a different ADB mode that you can use to push and install a zip using one command from your computer. Don&apos;t mix &lt;em&gt;adb sideload&lt;/em&gt; with &lt;em&gt;fasboot flash&lt;/em&gt; (&quot;线刷&quot;), though they both work over cable connection.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;adb sideload&lt;/em&gt; requires reliable USB cable connection.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Let your device be in sideload. You either do it in TWRP menu or by adb command line from your computer:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb reboot sideload/sideload-auto-reboot
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb devices
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;You will get:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;List of devices attached
afc75758	sideload
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Flash the zip ROM&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb sideload /path/to/rom.zip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;rom-custiomization&quot;&gt;ROM custiomization&lt;/h1&gt;

&lt;p&gt;Before flashing official zip ROM, delete builit-in promotional APKs to save storage. Alternatively, you have to delete them by &lt;em&gt;root&lt;/em&gt; apps after flashing.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;To add back a previously deleted app, &lt;em&gt;push&lt;/em&gt; both the apk and &lt;em&gt;odex&lt;/em&gt;. &lt;em&gt;install&lt;/em&gt; does NOT help in case of apk with separate &lt;em&gt;odex&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb remount
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb push /path/apk /system/app/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;You may &lt;em&gt;remount&lt;/em&gt; before &lt;em&gt;push&lt;/em&gt;ing to &lt;em&gt;/system/app&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Check newly pushed files permission mode.&lt;/li&gt;
      &lt;li&gt;You can also make a zip ROM to install just one app. Details refer to &lt;a href=&quot;http://bbs.nubia.cn/thread-786029-1-1.html&quot;&gt;努比亚z11精简包+系统程序中英文对照表&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To further delete a built-in apk,&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb shell pm list packages | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; example
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb pm uninstall nubia.example.cn
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb reboot recovery
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./adb shell
shell@NX531J:/ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find / &lt;span class=&quot;nt&quot;&gt;-iname&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*example*&apos;&lt;/span&gt;
shell@NX531J:/ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find / &lt;span class=&quot;nt&quot;&gt;-iname&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*example*&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-delete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Sometimes deleted apps reappear somehow. They are restored by Android cache partition. Wipe cache gets rid of that.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add personal apps to ROM&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Put your apk (i.e. &lt;em&gt;Example&lt;/em&gt;) into &lt;em&gt;/system/app/Example&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;If apk depends on system lib (check /META-INF/com/google/android/updater-script), do a &lt;em&gt;symlink&lt;/em&gt; to &lt;em&gt;/system/lib&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Lastly, check files modes.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;以下再以另一个例子来说明如何内置带有库（LIB）的软件。

我以来电通为例子

在电脑上用RAR打开“来电通.APK”。发现它是带有LIB目录的。

进入它，并把那两个SO文件拉出来，是的就是拉。然后放到手机的TF卡上。我一般喜欢放到个文件夹中。

这里记得把来电通的中文名改成一个你喜欢的英文名。比如说我的改成LDT1024.apk(如果文件名是英文，可以不不改掉。)

在RE中按住MENU 多选，选两个SO文件。复制它们到SYSTEM/LIB中。

同理，再回去把LDT1024. apk 拷到SYSTEM/APP中。

重启。接着你进去会发现，程序那里多出来了两个来电通的东东。一个是主程另一个来电通拔号。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;apktool&quot;&gt;&lt;a href=&quot;https://ibotpeaches.github.io/Apktool/&quot;&gt;apktool&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;To install apktool, at least java 1.7 is installed. Afterwards, just follow &lt;a href=&quot;https://ibotpeaches.github.io/Apktool/install/&quot;&gt;Install Instructions&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Put the two downloaded files into home directory &lt;em&gt;~/opt/apktool&lt;/em&gt; instead of &lt;em&gt;/usr/bin&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/opt/apktool
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x apktool&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./apktool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Linux wrapper script is &lt;em&gt;optional&lt;/em&gt; but we have to type a long command:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/opt/apktool
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;java &lt;span class=&quot;nt&quot;&gt;-jar&lt;/span&gt; apktool.jar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Framework resources&lt;/p&gt;

    &lt;p&gt;Every Apktool release contains internally the most up to date AOSP framework at the time of the release. This allows you to decode and build most apks without a problem. However, manufacturers add their own framework files in addition to the regular AOSP ones. To use apktool against these manufacturer apks you must first install the manufacturer framework files.&lt;/p&gt;

    &lt;p&gt;Framework files are usually a few built-in apks under &lt;em&gt;/system/framework&lt;/em&gt;. Nubia has two built-in framework files, namely &lt;em&gt;framework-nubia-res.apk&lt;/em&gt; and &lt;em&gt;framework-res.apk&lt;/em&gt;. We just need the former one for Apktool brings along an up-to-date &lt;em&gt;framework-res.apk&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./apktool &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; nubia /path/to/framework-nubia-res.apk 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t nubia&lt;/code&gt; sets a tag for the installed framwork which should be added to &lt;em&gt;decode&lt;/em&gt;, which otherwise would report &lt;em&gt;Can&apos;t find framework resources for package of id&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;By default, it&apos;s installed to &lt;em&gt;~/.local/share/apktool/framework&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://ibotpeaches.github.io/Apktool/documentation/&quot;&gt;Decompile/decode and build back&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;After decoding, we can find useful information on the app under &lt;em&gt;res/values-zh-rCN/string.xml&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;By default &lt;em&gt;/tmp&lt;/em&gt; is mounted as &lt;em&gt;noexec&lt;/em&gt;, which would cause &lt;em&gt;apktool build&lt;/em&gt; error like:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brut.common.BrutException: could not exec: [/tmp/brut_util_Jar_1093671213752336150.tmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;We either remount &lt;em&gt;/tmp&lt;/em&gt; as &lt;em&gt;exec&lt;/em&gt; or refer to &lt;a href=&quot;https://github.com/iBotPeaches/Apktool/issues/1011&quot;&gt;aapt&lt;/a&gt;. Firstly, extract directory &lt;em&gt;prebuilt/aapt&lt;/em&gt; from &lt;em&gt;apktool.jar&lt;/em&gt; to somewhere (i.e. &lt;em&gt;~/opt/apktool&lt;/em&gt;). Then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-a / --aapt&lt;/code&gt; parameter.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./apktool b &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; ./aapt/linux/64/aapt Test-apk/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;apps&quot;&gt;Apps&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;ConnectBot&lt;/p&gt;

    &lt;p&gt;Connectbot freezes after login? No response with &lt;a href=&quot;https://github.com/dragonlinux/connectbot/issues/493&quot;&gt;black screen&lt;/a&gt;? Please enable &lt;em&gt;Start shell session&lt;/em&gt; in host edit.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;LatinIME&lt;/p&gt;

    &lt;p&gt;By default, I have removed default AOSP input method &lt;em&gt;/system/app/LatinIME&lt;/em&gt; from official ROM in favor of Google Pinyin Input. Meanwhile I choose &lt;em&gt;require PIN/password to start device&lt;/em&gt; when setting lock screen PIN/password. In such case, I cannot boot the device since there is no stock input method to fill in PIN/password.&lt;/p&gt;

    &lt;p&gt;When confronted with the issue, I can temporarily &lt;em&gt;adb push&lt;/em&gt; AOSP LatinIM into system or use physical OTG keyboard.&lt;/p&gt;

    &lt;p&gt;After booting the device, change lock screen method to &lt;em&gt;pattern&lt;/em&gt; instead of &lt;em&gt;PIN/password&lt;/em&gt;, which does not depend on stock LatinIME.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;To be verified&lt;/strong&gt;: may be solved by adding &lt;em&gt;google-pinyin.apk&lt;/em&gt; into ROM &lt;em&gt;/system/app&lt;/em&gt; or &lt;em&gt;/system/priv-app/&lt;/em&gt;, thus flashing &lt;em&gt;google-pinyin&lt;/em&gt; as stock IME.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;OsmAnd+&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;obf&lt;/em&gt; maps data hidden link: &lt;a href=&quot;https://download.osmand.net/list.php&quot;&gt;obf link 1&lt;/a&gt;, &lt;a href=&quot;https://osmand.net/list.php&quot;&gt;obf link 2&lt;/a&gt;, and &lt;a href=&quot;http://download.osmand.net/rawindexes/&quot;&gt;obf link 3&lt;/a&gt;. Generated download link is as:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;http://dl5.osmand.net/download.php?standard=yes&amp;amp;file=Hong-kong_asia_2.obf.zip&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Hidden &lt;a href=&quot;https://osmand.net/help/&quot;&gt;Faq link&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;bootrecovery-img-manipulation&quot;&gt;boot/recovery img manipulation&lt;/h1&gt;

&lt;p&gt;Read &lt;a href=&quot;https://android.stackexchange.com/a/154621&quot;&gt;mkbootimg/unpackbootimg&lt;/a&gt;. You&apos;d better use &lt;em&gt;android_system_core&lt;/em&gt; version.&lt;/p&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://android.stackexchange.com/a/28315&quot;&gt;adb backup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Android/adb&quot;&gt;Gentoo adb&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://bbs.mfunz.com/space-uid-1339507.html&quot;&gt;XiNGRZ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://android.stackexchange.com/a/154621&quot;&gt;mkbootimg/unpackbootimg&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>CentOS RHEL</title>
   <link href="/2017/04/05/centos-rhel/"/>
   <updated>2017-04-05T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/04/05/centos-rhel</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#fedora-rhel-centos&quot; id=&quot;markdown-toc-fedora-rhel-centos&quot;&gt;Fedora RHEL CentOS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#module&quot; id=&quot;markdown-toc-module&quot;&gt;Module&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#rpm-yum-dnf&quot; id=&quot;markdown-toc-rpm-yum-dnf&quot;&gt;rpm yum dnf&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#rpm&quot; id=&quot;markdown-toc-rpm&quot;&gt;rpm&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#yum&quot; id=&quot;markdown-toc-yum&quot;&gt;yum&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#dnf&quot; id=&quot;markdown-toc-dnf&quot;&gt;dnf&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#repositories&quot; id=&quot;markdown-toc-repositories&quot;&gt;Repositories&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#epel-not-from-rhel&quot; id=&quot;markdown-toc-epel-not-from-rhel&quot;&gt;EPEL not from RHEL&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#inline-with-upstream-stable-ius&quot; id=&quot;markdown-toc-inline-with-upstream-stable-ius&quot;&gt;Inline with Upstream Stable (IUS)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#webtatic-deprecated&quot; id=&quot;markdown-toc-webtatic-deprecated&quot;&gt;Webtatic (DEPRECATED)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#centos-58&quot; id=&quot;markdown-toc-centos-58&quot;&gt;CentOS-5.8&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#upgrade-system&quot; id=&quot;markdown-toc-upgrade-system&quot;&gt;Upgrade System&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#rpmbuild&quot; id=&quot;markdown-toc-rpmbuild&quot;&gt;rpmbuild&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#extracting-rpm&quot; id=&quot;markdown-toc-extracting-rpm&quot;&gt;Extracting RPM&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#locale&quot; id=&quot;markdown-toc-locale&quot;&gt;locale&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ssh&quot; id=&quot;markdown-toc-ssh&quot;&gt;SSH&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#create-user-account&quot; id=&quot;markdown-toc-create-user-account&quot;&gt;Create User Account&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pipvirtualenv&quot; id=&quot;markdown-toc-pipvirtualenv&quot;&gt;Pip/Virtualenv&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ss&quot; id=&quot;markdown-toc-ss&quot;&gt;SS&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#server-json&quot; id=&quot;markdown-toc-server-json&quot;&gt;Server Json&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#tcp-fast-open&quot; id=&quot;markdown-toc-tcp-fast-open&quot;&gt;TCP Fast Open&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#a-quick-test&quot; id=&quot;markdown-toc-a-quick-test&quot;&gt;A quick test&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#systemd-unit&quot; id=&quot;markdown-toc-systemd-unit&quot;&gt;Systemd Unit&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#simple-type&quot; id=&quot;markdown-toc-simple-type&quot;&gt;simple Type&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#forking-type&quot; id=&quot;markdown-toc-forking-type&quot;&gt;forking Type&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#kcptun&quot; id=&quot;markdown-toc-kcptun&quot;&gt;kcptun&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;fedora-rhel-centos&quot;&gt;Fedora RHEL CentOS&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Fedora is a Linux distribution released under GPL.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Red Hat, Inc. copy the source code from Fedora, make modifications, release it as Red Hat Enterprise Linux (RHEL) distribution.&lt;/p&gt;

    &lt;p&gt;Due to GPL, Red Hat, Inc. is obligated to disclose RHEL source code. But Red Hat can make money from its professional after-sale services.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;CentOS (Community ENTerprise OS) is a Linux distribution built from the source of RHEL directly without any modification, with the intention of making CentOS binary compatible with RHEL such that library versions the same and binaries work on RHEL also work on CentOS.
    &lt;ol&gt;
      &lt;li&gt;The main purpose of CentOS is to make RHEL available to pulbic users, benefitting from Red Hat&apos;s professional Linux service.&lt;/li&gt;
      &lt;li&gt;Remove Red Hat, Inc. logo.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Fedora - RHEL - CentOS.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;module&quot;&gt;Module&lt;/h1&gt;

&lt;p&gt;Module is a new packaging feature brought in from RHEL 8.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Package&lt;/p&gt;

    &lt;p&gt;Traditional &lt;em&gt;.rpm&lt;/em&gt; file.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Group and Environment&lt;/p&gt;

    &lt;p&gt;A large set of packages as a whole for specific system categories like X window, desktop, security, development, etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Module is a collection of a few packages, as a logical unit for a specific project, like Php and Nginx.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Stream is the &lt;em&gt;upstream version&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Version is the &lt;em&gt;build version&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Profile is the sub-functionality of a module, similar to Gentoo&apos;s &lt;em&gt;tag&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;rpm-yum-dnf&quot;&gt;rpm yum dnf&lt;/h1&gt;

&lt;p&gt;The relation between &lt;em&gt;rpm&lt;/em&gt; (Redhat Package Manager) command and &lt;em&gt;yum&lt;/em&gt; (Yellow dog Updater, Modified) command is analogous to &lt;em&gt;dpkg&lt;/em&gt; and &lt;em&gt;apt-get&lt;/em&gt;. &lt;em&gt;dnf&lt;/em&gt; is the new version of &lt;em&gt;yum&lt;/em&gt; with performance improvement and &lt;em&gt;module&lt;/em&gt; feature. From RHEL 8 onwards, &lt;em&gt;dnf&lt;/em&gt; replaces &lt;em&gt;yum&lt;/em&gt; as the default manager.&lt;/p&gt;

&lt;p&gt;Basically, &lt;em&gt;yum&lt;/em&gt; is more intelligent than &lt;em&gt;rpm&lt;/em&gt;. &lt;em&gt;rpm&lt;/em&gt; wants to know the exact location of target &lt;em&gt;.rpm&lt;/em&gt; file while &lt;em&gt;yum&lt;/em&gt; only needs the package name. &lt;em&gt;yum&lt;/em&gt; also takes care of dependencies. However, &lt;em&gt;rpm&lt;/em&gt; is somehow a lightweight tool with concise output.&lt;/p&gt;

&lt;p&gt;Check &apos;SPECIFYING PACKAGE NAMES&apos; in the man page of &lt;em&gt;yum&lt;/em&gt; to check how to pass globs arguments. The full name of a &lt;em&gt;.rpm&lt;/em&gt; package is as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# &amp;lt;name&amp;gt;-&amp;lt;version&amp;gt;-&amp;lt;release&amp;gt;.&amp;lt;os&amp;gt;.&amp;lt;arch&amp;gt;.rpm

vim-enhanced-7.4.160-4.el7.x86_64
# name:     vim-enhanced
# version:  7.4.160
# release:  4
# os:       el7
# arch:     x86_64
# suffix:   rpm

centos-release-7-4.1708.el7.centos.x86_64
# name:     centos-release
# version:  7
# release:  4.1708
# os:       el7.centos
# arch:     x86_64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Package &lt;em&gt;version&lt;/em&gt; is also called &lt;em&gt;major version&lt;/em&gt;, indicating the upstream source version from developers. Package &lt;em&gt;release&lt;/em&gt; is also called &lt;em&gt;minor version&lt;/em&gt;, indicating the final &lt;em&gt;.rpm&lt;/em&gt; file by RHEL compliling/building/patching. Especially, RHEL may add customized patches or bug fixes to the major version, building a new &lt;em&gt;.rpm&lt;/em&gt; package to the repository.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;os&lt;/em&gt; may be el6 (rhel6), centos6, el5, suse11 etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By design, it is not possible to install difference versions of the same package alongside. The workaround is to make the new version a different package. For example, &lt;em&gt;python2&lt;/em&gt; and &lt;em&gt;python3&lt;/em&gt; are actually different package names.&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;rpm&lt;/em&gt; manages package file directly, maintaining a database of package information located under &lt;em&gt;/var/lib/rpm/&lt;/em&gt;. It does not care too much the package version but the RPM file you provided.&lt;/p&gt;

&lt;p&gt;Query installed packages:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rpm -qa &apos;globbing&apos;&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rpm -qa | grep &apos;regex&apos;&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# rpm -qi pkg; rpm -qip pkg.rpm                     # query pkg information&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rpm -qR pkg; rpm -qRp pkg.rpm                     # dependencies&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# rpm -ql pkg; rpm -qlp pkg.rpm                     # files in a package&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rpm -qf /path/to/file                             # package that owns the file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Verify. List discrepancies between installed files and files recorded in metadata from local RPM database.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rpm -V pkg; rpm -Vp pkg.rpm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Kering:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rpm --import /path/to/key.pub&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rpmkeys --import http://www.example.com/key.pub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once imported, all public keys in the keyring can be managed as a package. Commands applied to a package also apply to a key like query, erase, information etc.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# ls /etc/pki/rpm-gpg/&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# rpm -qa gpg-pubkey*&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# rpm -qi gpg-pubkey-db42a60e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Signature. To verify a RPM file is not corrupted (e.g. due to network transmission) and correctly signed (by developer).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# verify MD5&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ok&lt;/span&gt;
rpm &lt;span class=&quot;nt&quot;&gt;-Kv&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--nosignature&lt;/span&gt; kong-enterprise-edition-3.3.1.0.rhel8.amd64.rpm
kong-enterprise-edition-3.3.1.0.rhel8.amd64.rpm:
    Header SHA256 digest: OK
    Payload SHA256 digest: OK

&lt;span class=&quot;c&quot;&gt;# verify both MD5 and signature&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# MD5: ok&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# signature: key not found&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-Kv&lt;/span&gt; kong-enterprise-edition-3.3.1.0.rhel8.amd64.rpm
kong-enterprise-edition-3.3.1.0.rhel8.amd64.rpm:
    Header V4 RSA/SHA256 Signature, key ID 1a62ff7c: NOKEY
    Header SHA256 digest: OK
    Payload SHA256 digest: OK
    V4 RSA/SHA256 Signature, key ID 1a62ff7c: NOKEY

&lt;span class=&quot;c&quot;&gt;# get signing key ID from RPM file&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-qip&lt;/span&gt; kong-enterprise-edition-3.3.1.0.rhel8.amd64.rpm | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;Signature
warning: kong-enterprise-edition-3.3.1.0.rhel8.amd64.rpm: Header V4 RSA/SHA256 Signature, key ID 1a62ff7c: NOKEY
Signature   : RSA/SHA256, Sat 01 Jul 2023 04:11:14 AM UTC, Key ID 998dff461a62ff7c

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-qp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--queryformat&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%{NAME}-%{VERSION}-%{RELEASE} %{SIGPGP:pgpsig}\n&apos;&lt;/span&gt; kong-enterprise-edition-3.3.1.0.rhel8.amd64.rpm
kong-enterprise-edition-3.3.1.0-1 RSA/SHA256, Sat 01 Jul 2023 04:11:15 AM UTC, Key ID 998dff461a62ff7c

&lt;span class=&quot;c&quot;&gt;# import the signing key&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; https://docs.konghq.com/assets/keys/2023-rpm.asc

&lt;span class=&quot;c&quot;&gt;# list GPG key in RPM database&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-qa&lt;/span&gt; gpg-pubkey&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
gpg-pubkey-be1229cf-5631588c
gpg-pubkey-fd431d51-4ae0493b
gpg-pubkey-1a62ff7c-639852e2
gpg-pubkey-d4082792-5b32db75

&lt;span class=&quot;c&quot;&gt;# examine the GPG key&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-qi&lt;/span&gt; gpg-pubkey-1a62ff7c-639852e2
Name        : gpg-pubkey
Version     : 1a62ff7c
Release     : 639852e2
Architecture: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;none&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Install Date: Mon 03 Jul 2023 05:45:24 AM UTC
Group       : Public Keys
Size        : 0
License     : pubkey
Signature   : &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;none&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Source RPM  : &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;none&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Build Date  : Tue 13 Dec 2022 10:24:34 AM UTC
Build Host  : localhost
Relocations : &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;not relocatable&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Packager    : Bazel Testing
Summary     : gpg&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Bazel Testing&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Description :
&lt;span class=&quot;nt&quot;&gt;-----BEGIN&lt;/span&gt; PGP PUBLIC KEY BLOCK-----
Version: rpm-4.14.3 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;NSS-3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
...

&lt;span class=&quot;c&quot;&gt;# verify again&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-Kv&lt;/span&gt; kong-enterprise-edition-3.3.1.0.rhel8.amd64.rpm
kong-enterprise-edition-3.3.1.0.rhel8.amd64.rpm:
    Header V4 RSA/SHA256 Signature, key ID 1a62ff7c: OK
    Header SHA256 digest: OK
    Payload SHA256 digest: OK
    V4 RSA/SHA256 Signature, key ID 1a62ff7c: OK
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Install:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rpm -ivvh --test /path/to/pkg.rpm      # dry run&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rpm -ivh /path/to/pkg.rpm              # install&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rpm --reinstall -vh /path/to/same.rom  # reinstall&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# rpm -Uvh /path/to/pkg.rpm              # upgrade&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rpm -Fvh /path/to/pkg.rpm              # refresh&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rpm -Fvh --force /path/to/old.rpm      # downgrade&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;The path can be an ftp/http URL.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i, --install&lt;/code&gt; is the general form of installing a package.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-U, --upgrade&lt;/code&gt; is the combination of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i, --install&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-e&lt;/code&gt;. It firstly install a package and then erase earlier versions if present.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-U&lt;/code&gt; does not require an earlier version is installed, so it can be a replacement of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-F, --freshen&lt;/code&gt; is similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-U&lt;/code&gt; but mandates an earlier version is already installed.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--force&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--replacepkgs&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--replacefiles&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--oldpackage&lt;/code&gt; do the same thing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Uninstall/Erase:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rpm -evv pkg                     # uninstall a pkg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;p&gt;The &lt;em&gt;main&lt;/em&gt; configuration of YUM is &lt;em&gt;/etc/yum.conf&lt;/em&gt; and specific repository configuration files are placed in &lt;em&gt;/etc/yum.repos.d/&lt;/em&gt;. Within the main configuration file, &lt;em&gt;cachedir&lt;/em&gt; defines the location of cached &lt;em&gt;.rpm&lt;/em&gt; packages (defaults to &lt;em&gt;/var/cache/yum/$basearch/$releasever&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;By default, of the built-in repositories, only &apos;CentOS-Base.repo&apos; is enabled.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$releasever&lt;/code&gt; indicates the main version. For example, the main version of CentOS 5.8 is 5.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$arch&lt;/code&gt; indicates the architecture like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x8_64&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i386/i586/i686&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$basearch&lt;/code&gt; is similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$arch&lt;/code&gt;, but is &lt;em&gt;base&lt;/em&gt; architecture: either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x86_64&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i386&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cache:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;yum &lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;sub-command]

~ &lt;span class=&quot;c&quot;&gt;# yum clean [ all | packages | metadata | expire-cache | rpmdb | plugins ]&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum makecache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After any edits of &lt;em&gt;repo&lt;/em&gt; files, in order to clear any cached information, and make sure the changes are immediately recoginized, as root run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yum clean all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Query:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum history&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum list [all | installed | available | updates ] [pkg]&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum info [all | installed | available | updates ] [pkg] # more details&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum search pkg&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum --showduplicates search pkg    # show all versions&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum repolist [--all | --enabled | --disabled]&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum check-update&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum upgrade [pkg]&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum provides /path/to/file             # rpm -qf&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# repoquery -f /path/to/file&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# repoqeury --provides /path/to/file&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# repoqeury --whatprovides /path/to/file&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# repoquery -l pkg&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# repoquery --deplist pkg&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# repoquery --whatdepends pkg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;update&lt;/em&gt; is synonym to &lt;em&gt;upgrade&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;list –updates&lt;/em&gt; is almost the same as &lt;em&gt;check-update&lt;/em&gt;. As the command form implies, &lt;em&gt;check-update&lt;/em&gt; is useful in Shell script while &lt;em&gt;list –updates&lt;/em&gt; is for humans on the command line.&lt;/p&gt;

    &lt;p&gt;Please pay attention, their exit status code difference.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Make sure &lt;em&gt;yum-utils&lt;/em&gt; is installed to use &lt;em&gt;repoquery&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Install:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum [-y] install pkg1 pkg2&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# will install dependency automatically&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum install /path/to/pkg.rpm&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum reinstall pkg1 pkg2&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum upgrade pkg1 pkg2&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum remove pkg1 pkg2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To install packages for &lt;em&gt;group&lt;/em&gt; or &lt;em&gt;environment&lt;/em&gt; set:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum group summary&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum group [ list | info |install | upgrade | remove | mark ] [grp]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;p&gt;&lt;em&gt;dnf&lt;/em&gt; is compatible with but more powerful than &lt;em&gt;yum&lt;/em&gt;. One of the newest feature provided is &lt;em&gt;module&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# dnf module -h&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# dnf module list nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# dnf module info nginx&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# NAME:STREAM:VERSION:CONTEXT:ARCH/PROFILE&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# dnf module info nginx:1.16:8010020191122190044:cdc1202b:x86_64/common&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# dnf module install nginx:1.14/common&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The purpose of &lt;em&gt;module&lt;/em&gt; is to manage package versions and profiles in an integrated way. The following two methods is equivalent:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# dnf module install nginx&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# dnf install nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The only difference is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnf module&lt;/code&gt; can provide better control when selecting pakage stream, version, arch etc.&lt;/p&gt;

&lt;p&gt;The following example shows how to control repo with &lt;em&gt;dnf&lt;/em&gt; (applying to &lt;em&gt;yum&lt;/em&gt; as well):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;help &lt;/span&gt;repolist 
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf repolist &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--all&lt;/span&gt; | &lt;span class=&quot;nt&quot;&gt;--enabled&lt;/span&gt; | &lt;span class=&quot;nt&quot;&gt;--disabled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf config-manager &lt;span class=&quot;nt&quot;&gt;--add-repo&lt;/span&gt; /etc/yum.repos.d/oracle-epel-ol8.repo

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;enabled /etc/yum.repos.d/oracle-epel-ol8.repo
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf config-manager &lt;span class=&quot;nt&quot;&gt;--set-enabled&lt;/span&gt; ol8_developer_EPEL
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;duso dnf config-manager &lt;span class=&quot;nt&quot;&gt;--set-disabled&lt;/span&gt; ol8_developer_EPEL

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dnf &lt;span class=&quot;nt&quot;&gt;--enablerepo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;repo1,repo2 &lt;span class=&quot;nt&quot;&gt;-disablerepo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;repo3,repo4 &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pkg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;repositories&quot;&gt;Repositories&lt;/h1&gt;

&lt;p&gt;Of the &lt;a href=&quot;https://wiki.centos.org/AdditionalResources/Repositories&quot;&gt;3rd party repositories&lt;/a&gt;, IUS and Remi (both depend on EPEL) is recommended over Webtatic.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum repolist [all|enabled|disabled]&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum-config-manager --add-repo &amp;lt;repo-url&amp;gt;&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum update -y&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum repolist [all|enabled|disabled]&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum-config-manager --disable &amp;lt;repo-id&amp;gt;&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# yum-config-manager --enable &amp;lt;repo-id&amp;gt;&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum update -y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To remove a repo, just remove the file within &lt;em&gt;/etc/yum.repos.d&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;epel-not-from-rhel&quot;&gt;EPEL not from RHEL&lt;/h2&gt;

&lt;p&gt;EPEL (Extra Packages for Enterprise Linux) is open source and free community based repository project from &lt;a href=&quot;https://fedoraproject.org/wiki/EPEL&quot;&gt;Fedora&lt;/a&gt; team which provides 100% high quality add-on software packages.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum info epel-release&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# yum install epel-release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To specify repository when installing package:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum --enablerepo=epel install nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--enablerepo&lt;/code&gt; option overides the permanent option setting in the &lt;em&gt;/etc/yum/*.repo&lt;/em&gt; files for only the current command. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--disablerepo&lt;/code&gt; does the opposite for enabled repos.&lt;/p&gt;

&lt;h2 id=&quot;inline-with-upstream-stable-ius&quot;&gt;&lt;a href=&quot;https://ius.io/GettingStarted/&quot;&gt;Inline with Upstream Stable (IUS)&lt;/a&gt;&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rpm -Uvh https://centos7.iuscommunity.org/ius-release.rpm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Read &lt;a href=&quot;https://ius.io/Usage/&quot;&gt;IUS Usage&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h2 id=&quot;webtatic-deprecated&quot;&gt;Webtatic (DEPRECATED)&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://webtatic.com/projects/yum-repository/&quot;&gt;Webtatic Yum repository&lt;/a&gt; is a CentOS/RHEL repository containing updated web-related packages like &lt;em&gt;git&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;centos-58&quot;&gt;&lt;a href=&quot;https://unix.stackexchange.com/q/359902&quot;&gt;CentOS-5.8&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;CentOS-5 reached the end of its lifecycle as of March 31, 2017. The official &lt;a href=&quot;http://mirror.centos.org/centos/5/readme&quot;&gt;baseurl&lt;/a&gt; is deprecated and moved to a backup location &lt;a href=&quot;http://vault.centos.org/5.8/&quot;&gt;Vault&lt;/a&gt;. Packages there is no longer maintained or upgraded, and may suffer from security risks.&lt;/p&gt;

&lt;p&gt;However, we sometimes have to maintain ancient releases for whatever reasons. To install packages through &lt;em&gt;yum&lt;/em&gt;, &lt;a href=&quot;https://www.centos.org/forums/viewtopic.php?t=62130&quot;&gt;point repositories to the new location&lt;/a&gt;: either manually edit &lt;em&gt;/etc/yum.repos.d/CentOS-Base.repo&lt;/em&gt; or install &lt;em&gt;centos-release-5-8.el5.centos.x86_64.rpm&lt;/em&gt; file.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;For each section (i.e. Base) Comment out both the &lt;em&gt;mirrorlist=&lt;/em&gt; and &lt;em&gt;baseurl=&lt;/em&gt; lines.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add a new baseurl line:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;baseurl=http://vault.centos.org/5.8/os/$basearch/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Replace &lt;em&gt;/os/&lt;/em&gt; part approriately for other sections like &lt;em&gt;/updates/&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;It is highly recommended to replace 5.8 with 5.11, upgrading the system to CentOS 5.11&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Alternatively, install the corresponding repository package:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ # wget http://vault.centos.org/5.11/os/x86_64/CentOS/centos-release-5-11.el5.centos.x86_64.rpm
root@tux ~ # rpm -Uvh centos-release-5-11.el5.centos.x86_64.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;For other repositories like EPEL, Webtatic etc., find their archive URL and repeat the same procedures.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Update&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# rpm -q centos-release; cat /etc/redhat-release; cat /etc/centos-release&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# yum clean all; yum makecache&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# yum list updates; yum update&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# reboot&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# yum install epel-release; yum install git&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is an example of manually edited Centos-Base.repo:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the 
# remarked out baseurl= line instead.
#
#

[base]
name=CentOS-$releasever - Base
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;amp;arch=$basearch&amp;amp;repo=os
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
baseurl=http://vault.centos.org/5.11/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#released updates 
[updates]
name=CentOS-$releasever - Updates
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;amp;arch=$basearch&amp;amp;repo=updates
#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
baseurl=http://vault.centos.org/5.11/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;amp;arch=$basearch&amp;amp;repo=extras
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
baseurl=http://vault.centos.org/5.11/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;amp;arch=$basearch&amp;amp;repo=centosplus
#baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/
baseurl=http://vault.centos.org/5.11/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#contrib - packages by Centos Users
[contrib]
name=CentOS-$releasever - Contrib
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;amp;arch=$basearch&amp;amp;repo=contrib
#baseurl=http://mirror.centos.org/centos/$releasever/contrib/$basearch/
baseurl=http://vault.centos.org/5.11/contrib/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;upgrade-system&quot;&gt;Upgrade System&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# dnf check-update&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# dnf upgrade kernel&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# dnf upgrade&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# reboot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;rpmbuild&quot;&gt;rpmbuild&lt;/h1&gt;

&lt;p&gt;For how to build RPM package, refer to &quot;logging/filebeat-zookeeper-kafka&quot;.&lt;/p&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://www.redhat.com/sysadmin/create-rpm-package&quot;&gt;How to create a Linux RPM package&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;extracting-rpm&quot;&gt;Extracting RPM&lt;/h2&gt;

&lt;p&gt;Upon receving a &lt;em&gt;.rpm&lt;/em&gt; file, we can extract the contents with &lt;em&gt;rpm2cpio&lt;/em&gt; and &lt;em&gt;cipo&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rpm2cpio /path/to/pkg.rpm | cpio &lt;span class=&quot;nt&quot;&gt;-idmv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--no-preserve-owner&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--no-absolute-filenames&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; dst] &lt;span class=&quot;s1&quot;&gt;&apos;*resty*&apos;&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-i&lt;/code&gt;: extract; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; list instead of extract.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d&lt;/code&gt;: make directories &lt;em&gt;dst&lt;/em&gt; and others on demand.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-m&lt;/code&gt;: preserve modification time.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-v&lt;/code&gt;: verbose.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--no-preserve-owner&lt;/code&gt;: replace the ownership with current user.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--no-absolute-filenames&lt;/code&gt;: remove the root dir prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;, and replace it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-D&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*resty*&lt;/code&gt; is a Shell globbing pattern to extract only specific files. By default, extract all files.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;locale&quot;&gt;locale&lt;/h1&gt;

&lt;p&gt;Redhad-based distributions places &lt;em&gt;locale&lt;/em&gt; customization in &lt;em&gt;/etc/locale.conf&lt;/em&gt;. Check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man locale.conf&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;ssh&quot;&gt;SSH&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# ssh-add&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# ssh-copy-id -p 12345 root@12.23.56.78&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# add an entry to ~/.ssh/config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;create-user-account&quot;&gt;Create User Account&lt;/h1&gt;

&lt;p&gt;Check &lt;a href=&quot;/2015/03/25/gentoo-installation/&quot;&gt;useradd&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# ssh-copy-id -p 12345 username@12.34.56.78&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# add an entry to ~/.ssh/config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;pipvirtualenv&quot;&gt;Pip/Virtualenv&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# yum install python-pip python-virtualenv&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# pip install -U pip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;ss&quot;&gt;SS&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p ~/opt/pyvenv2.6&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# virtualenv --system-site-packages ~/opt/pyvenv2.6&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# pip install git+https://github.com/shadowsocks/shadowsocks.git@master&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# wget https://github.com/shadowsocks/shadowsocks/archive/master.zip&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# pip install master.zip&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;server-json&quot;&gt;Server Json&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# mkdir -p /etc/shadowsocks&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# vi /etc/shadowsocks/server.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Fill in the fileds without any comments:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;::0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3900&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local_address&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mypassword&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;timeout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;aes-256-cfb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fast_open&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;workers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;tcp-fast-open&quot;&gt;TCP Fast Open&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# vi /etc/sysctl.d/10-tcp-fast-open.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# net.ipv4.tcp_fastopen = 3&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# sysctl -p /etc/sysctl.d/10-tcp-fast-open.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Unfortunately CentOS 7 does not satisfy lower kernel bound - 3.7.1.&lt;/li&gt;
  &lt;li&gt;It should be enabled on cleint and server simutaneously.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;a-quick-test&quot;&gt;A quick test&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# ssserver -c /etc/shadowsocks/server.json --user nobody -d start -vv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;systemd-unit&quot;&gt;Systemd Unit&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Please reinstall Shadowsocks into system-wide location. The above &lt;em&gt;virtualenv&lt;/em&gt; version was just a test.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# vi /etc/systemd/system/shadowsocks.service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;simple-type&quot;&gt;simple Type&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Unit]
Description=Shadowsocks Server
After=network.target

[Service]
Type=simple
PermissionsStartOnly=true
ExecStartPre=/usr/bin/mkdir -p /run/shadowsocks
ExecStartPre=/usr/bin/chown nobody:nobody /run/shadowsocks
ExecStartPre=/usr/bin/su -s /bin/bash -c &quot;/usr/local/bin/kcptun-server -c /etc/shadowsocks/kcptun.json &amp;amp;&quot; nobody
ExecStart=/usr/bin/ssserver -c /etc/shadowsocks/server.json
Restart=on-abort
User=nobody
Group=nobody
UMask=0027

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please be noted that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;simple&lt;/em&gt; Type is used so that Shadowsocks does not &lt;em&gt;forking&lt;/em&gt; itself so that daemon mode is handed over to &lt;em&gt;systemd&lt;/em&gt;.
    &lt;ol&gt;
      &lt;li&gt;Do &lt;em&gt;not&lt;/em&gt; add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d start/stop/restart&lt;/code&gt; arguments to ExecStart&lt;/li&gt;
      &lt;li&gt;No PIDFile and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--pid-file&lt;/code&gt; required. Read more on &lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=723942#c4&quot;&gt;doesn&apos;t make sense to set PIDFile= by simple services&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;You may find a special line with &lt;em&gt;kcptun&lt;/em&gt;. Neglect it now for it will be discussed later on.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://yuyii.com/2015/12/28/shadowsocks-systemd/&quot;&gt;ref1&lt;/a&gt; and &lt;a href=&quot;http://www.leyar.me/Compile-shadowsocks-libev-in-CentOS7/&quot;&gt;ref2&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;forking-type&quot;&gt;forking Type&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Unit]
Description=Shadowsocks Server
After=network.target

[Service]
Type=forking
PermissionsStartOnly=true
PIDFile=/run/shadowsocks/ss.pid
ExecStartPre=/usr/bin/mkdir -p /run/shadowsocks
ExecStartPre=/usr/bin/chown nobody:nobody /run/shadowsocks
ExecStartPre=/usr/bin/su -s /bin/bash -c &quot;/usr/local/bin/kcptun-server -c /etc/shadowsocks/kcptun.json &amp;amp;&quot; nobody
ExecStart=/usr/bin/ssserver -d start -c /etc/shadowsocks/ss.json --pid-file /run/shadowsocks/ss.pid --log-file /run/shadowsocks/ss.log
Restart=on-abort
User=nobody
Group=nobody
UMask=0027

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;kcptun&quot;&gt;&lt;a href=&quot;https://github.com/xtaci/kcptun&quot;&gt;kcptun&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;kcptun&lt;/em&gt; estabilishs a KCP tunnel to speed up TCP connection by encapsulating TC packets within UDP flooding. It may introduce twice or even triple traffic depending on arguments choosen. You are advised to use it only in WI-FI environment.&lt;/p&gt;

&lt;p&gt;To add &lt;em&gt;kcptun&lt;/em&gt; support, just insert a line into Systemd service file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ExecStartPre=/usr/bin/su -s /bin/bash -c &quot;/usr/local/bin/kcptun-server -c /etc/shadowsocks/kcptun.json &amp;amp;&quot; nobody
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Attention to trailing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-c&lt;/code&gt; argument.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Virtual Private Network (VPN)</title>
   <link href="/2017/03/20/vpn/"/>
   <updated>2017-03-20T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/03/20/vpn</id>
   <content type="html">&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;VPN is a &lt;em&gt;tunneling protocol&lt;/em&gt; (TP) designed to facilitate travel employees&apos; networking connection back to office (i.e. headquarter).&lt;/p&gt;

    &lt;p&gt;However VPN can do more than that. For example, we use VPN to bypass firewall, ISP censorship etc. We call such VPN as Personal VPN.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are many VPNs implementations over the world to choose from, which includes but are not limited to:&lt;/p&gt;

    &lt;p&gt;PPTP, L2TP/IPSec, SSTP, OpenVPN, etc. Among of them, OpenVPN is the most widely deployed but rather complicated.&lt;/p&gt;

    &lt;p&gt;Wireguard emerges as a state-of-the-art VPN technology based on DH key exchange and Poly1305 encryption.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Logically, most VPNs locate at link layer (layer 2) offering services to IP layer (layer 3). On the other hand VPN itself sits on top of TCP/UDP layer. Almost all VPNs create virtual interface at system level to which kernel transmits application IP packets.&lt;/p&gt;

    &lt;p&gt;VPN service either resides in kernel (i.e. WireGuard kernel module or built-in tree) or run as a daemon at userspace space. Obviously, the former has greater performance.&lt;/p&gt;

    &lt;p&gt;Upon receving IP payload, VPN encapsulates application&apos;s IP payload into VPN TCP or UDP packets which in turn are encapsulated into the Internet IP packets again.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Generally, UDP VPN (i.e. WireGuard) is faster than TCP VPN (OpenVPN) but less reliable.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;pptp&quot;&gt;PPTP&lt;/h2&gt;

&lt;p&gt;Point-to-Point Tunneling Protocol (PPTP). A specification for PPTP was published in July 1999 as RFC 2637.&lt;/p&gt;

&lt;p&gt;PPTP has many known security issues, and it&apos;s likely the NSA (and probably other intelligence agencies) are decrypting these supposedly &quot;secure&quot; connections. That means attackers and more repressive governments would have an easier way to compromise these connections.&lt;/p&gt;

&lt;p&gt;PPTP is common and easy to set up. PPTP clients are built into many platforms, including Windows, Android etc. That&apos;s the only advantage, and it&apos;s not worth it. It&apos;s time to move on.&lt;/p&gt;

&lt;p&gt;In Summary: PPTP is an obselete, old and vulnerable, although integrated into common operating systems and easy to set up. Stay away!&lt;/p&gt;

&lt;h2 id=&quot;l2tpipsec&quot;&gt;L2TP/IPsec&lt;/h2&gt;

&lt;p&gt;L2TPv3 was proposed as standard RFC 3931 in 2005.&lt;/p&gt;

&lt;p&gt;Layer 2 Tunneling Protocol (L2TP) is a tunneling protocol used to support virtual private networks (VPNs) or as part of the delivery of services by ISPs. It does not provide any encryption or confidentiality by itself. Rather, it relies on an encryption protocol that it passes within the tunnel to provide privacy.&lt;/p&gt;

&lt;p&gt;Since L2TP is a VPN protocol that doesn&apos;t offer any encryption, it&apos;s usually implemented along with IPsec encryption. This is a &lt;em&gt;slower&lt;/em&gt; solution than OpenVPN. The traffic must be converted into L2TP form, and then encryption added on top with IPsec. It&apos;s a two-step process.&lt;/p&gt;

&lt;h2 id=&quot;sstp&quot;&gt;SSTP&lt;/h2&gt;

&lt;p&gt;Secure Socket Tunneling Protocol (SSTP) was introduced in Windows Vista Service Pack 1. It&apos;s a &lt;em&gt;proprietary&lt;/em&gt; Microsoft protocol, and is best supported on Windows. It may be more stable on Windows because it&apos;s integrated into the operating system whereas OpenVPN isn&apos;t — that&apos;s the biggest potential advantage. Some support for it is available on other operating systems, but it&apos;s nowhere near as widespread.&lt;/p&gt;

&lt;h1 id=&quot;openvpn&quot;&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/OpenVPN&quot;&gt;OpenVPN&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;Unlike PPTP and L2TP (proposed to RFC as standards), OpenVPN is actively maintained by &lt;a href=&quot;https://openvpn.net&quot;&gt;OpenVPN Technologies, Inc.&lt;/a&gt;. Apart from the free &lt;a href=&quot;https://openvpn.net/index.php/open-source.html&quot;&gt;OpenVPN Community Edition (CE)&lt;/a&gt;, OpenVPN Technologies, Inc. provides proprietary solution - &lt;a href=&quot;https://openvpn.net/index.php/access-server/overview.html&quot;&gt;OpenVPN Access Server (AS)&lt;/a&gt;. The proprietary OpenVPN AS is almost the same to free OpenVPN CE, with advantage of easy configuration and deployment (web interface).&lt;/p&gt;

&lt;p&gt;OpenVPN uses open-source technologies like the OpenSSL encryption library and SSL v3/TLS v1 protocols. It can be configured to run on any port, so you could configure a server to work over TCP port 443.&lt;/p&gt;

&lt;p&gt;OpenVPN support isn&apos;t integrated into popular desktop or mobile operating systems. Connecting to an OpenVPN network requires extra installation - either a desktop application or a mobile app. Yes, you can even use mobile apps to connect to OpenVPN networks on Apple&apos;s iOS.&lt;/p&gt;

&lt;h2 id=&quot;client&quot;&gt;Client&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Android: OpenVPN for Android and OpenConnect (open source; no root requirement).&lt;/li&gt;
  &lt;li&gt;iOS: OpenVPN Connect (closed source).&lt;/li&gt;
  &lt;li&gt;GNU/Linux: &lt;em&gt;net-vpn/openvpn&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;create-pki&quot;&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Easy-rsa&quot;&gt;Create PKI&lt;/a&gt;&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;Username/password authentication is discouraged for sake of anonymity and privacy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To set up OpenVPN server/client, we need to create Public Key Infrastructure (PKI).&lt;/p&gt;

&lt;p&gt;OpenVPN relies on a bidirectional authentication strategy, so the client must authenticate the server&apos;s certificate and in parallel, the server must authenticate the client&apos;s certificate. This is accomplished by the 3rd party&apos;s signature (the CA) on both the client and server certificates. Once this is established, further checks are performed before the authentication is complete.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;CA&lt;/p&gt;

    &lt;p&gt;A public master Certificate Authority (CA) certificate and a private key thereof. CA is the root of trust web.&lt;/p&gt;

    &lt;p&gt;(ca.key, ca.pub, ca.crt).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Server/Client key&lt;/p&gt;

    &lt;p&gt;A separate public certificate and private key pair (hereafter referred to as a certificate) for each server and each client.&lt;/p&gt;

    &lt;p&gt;(server.key, server.pub. server.crt); (client.key, client.pub, client.crt).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Other files&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;tls-auth&lt;/em&gt; key file; &lt;em&gt;crl-verify&lt;/em&gt; pem file; &lt;em&gt;dh&lt;/em&gt; pem file etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;An &lt;em&gt;.ovpn&lt;/em&gt; file (can be imported) simplifies configuration.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Security</title>
   <link href="/2017/03/10/security/"/>
   <updated>2017-03-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/03/10/security</id>
   <content type="html">&lt;p&gt;In this post, &lt;em&gt;security&lt;/em&gt; refers to cryptography, authentication, signing, password management, confidential communication and implementation thereof.&lt;/p&gt;

&lt;h1 id=&quot;prerequisite&quot;&gt;Prerequisite&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;Security -&amp;gt; Privacy -&amp;gt; Anonymity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Security (of data)&lt;/p&gt;

    &lt;p&gt;When talking about &lt;em&gt;security&lt;/em&gt;, we refer to securing the &lt;em&gt;data contents&lt;/em&gt;, which must meet three basic prerequisite: &lt;em&gt;confidentiality&lt;/em&gt;, &lt;em&gt;availibility&lt;/em&gt;, and &lt;em&gt;integrity&lt;/em&gt;. To guarantee data security, people encrypt data, store data in private place, etc.&lt;/p&gt;

    &lt;p&gt;Please be noted data &lt;em&gt;security&lt;/em&gt; is a &lt;em&gt;static&lt;/em&gt; state of data management, serving as the mean to data &lt;em&gt;privacy&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Privacy (of data)&lt;/p&gt;

    &lt;p&gt;Unlike static state of data security, &lt;em&gt;privacy&lt;/em&gt; concerns &lt;em&gt;utilizing&lt;/em&gt; secure data to ensure only authorized users can access it while unauthorized user cannot.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Anonymity (of user)&lt;/p&gt;

    &lt;p&gt;Anonymity means &lt;em&gt;disconnection&lt;/em&gt; between user &lt;em&gt;identify&lt;/em&gt; and Internet &lt;em&gt;activity&lt;/em&gt;. Identity is user&apos;s electronic representation, mainly consisting of computer mac address, browser fingerprint, email account, etc. ISP and end web servers can easily trace your identity by sniffing Internet communication.&lt;/p&gt;

    &lt;p&gt;Without security and privacy, anonymity is impossible.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;pgp---encryption&quot;&gt;PGP - Encryption&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Open Pretty Good Privacy (OpenPGP)&lt;/p&gt;

    &lt;p&gt;OpenPGP is an IETF standard proposed by PGP inc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;PGP&lt;/p&gt;

    &lt;p&gt;PGP is a proprietary software in accord with OpenGPG standard, previously own by PGP inc. now acquired by Symantec Corp.&lt;/p&gt;

    &lt;p&gt;PGP software comes before OpenPGP standard. In order to let PGP software thrive, PGP inc. proposed OpenPGP standard (PGP-complicant) to IETF.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;GNU Privacy Guard (GnuPG)&lt;/p&gt;

    &lt;p&gt;GnuPG is another OpenGPG implementation free of distribution that obeys GNU General Public License (GPL).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are other PGP-compliant software such as GoAnywhere OpenPGP Studio.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ssh---transmission&quot;&gt;SSH - Transmission&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Secure Shell (SSH)&lt;/p&gt;

    &lt;p&gt;SSH is a cryptographic network &lt;em&gt;protocol&lt;/em&gt; for operating network services securely over an unsecured network. The best known example application is for remote login to computer systems by users.&lt;/p&gt;

    &lt;p&gt;SSH was designed as a replacement for Telnet and for unsecured remote shell protocols such as the Berkeley rlogin, rsh, and rexec protocols.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;OpenBSD Secure Shell (OpenSSH)&lt;/p&gt;

    &lt;p&gt;OpenSSH started as a fork of the free SSH program, developed by Tatu Ylönen; later versions of Ylönen&apos;s SSH were proprietary software, offered by SSH Communications Security. OpenSSH was first released as part of the OpenBSD operating system in 1999.&lt;/p&gt;

    &lt;p&gt;OpenBSD is a free and open source Unix-like computer operating system descended from Berkeley Software Distribution (BSD), a Research Unix derivative developed at the University of California, Berkeley.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SFTP/SCP etc.&lt;/p&gt;

    &lt;p&gt;SFTP/SCP are secure version of FTP/CP.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;cryptography-library&quot;&gt;Cryptography library&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;GnuTLS and OpenSSH are different implementations of SSL/TLS/DTLS protocols.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;gnutls&quot;&gt;GnuTLS&lt;/h2&gt;

&lt;p&gt;GnuTLS is a secure communications library implementing the SSL, TLS and DTLS protocols and technologies around them.&lt;/p&gt;

&lt;p&gt;GnuPG depends on GnuTLS library.&lt;/p&gt;

&lt;h2 id=&quot;openssl&quot;&gt;OpenSSL&lt;/h2&gt;

&lt;p&gt;OpenSSL is a toolkit implementing SSL v2/v3 and TLS protocols with full-strength cryptography world-wide.&lt;/p&gt;

&lt;p&gt;OpenSSH is a program depending on OpenSSL the library, specifically OpenSSH uses the &lt;em&gt;libcrypto&lt;/em&gt; part of OpenSSL.&lt;/p&gt;

&lt;h1 id=&quot;summary&quot;&gt;Summary&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;OpenGPG/SSH - protocol standard.&lt;/li&gt;
  &lt;li&gt;GnuPG/OpenSSH - implementaion.&lt;/li&gt;
  &lt;li&gt;Gnutls/OpenSSL - underlying library.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;publicprivate-key&quot;&gt;Public/Private key&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;Losing sole possession of your private key is catastrophic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;gnupg&quot;&gt;GnuPG&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Public key encrypts message to you. Private key decryptes message recevied; signs document in your name.&lt;/li&gt;
  &lt;li&gt;The term key usually refers to &lt;em&gt;key pair&lt;/em&gt; which is a coulple of public key (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--list-keys&lt;/code&gt;) and private key (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--list-secret-keys&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;By default, two key pairs are generated, of which one pair is called &lt;em&gt;master key&lt;/em&gt; pair for &lt;em&gt;Signing&lt;/em&gt; and &lt;em&gt;Certifying&lt;/em&gt; while another one is &lt;em&gt;subkey&lt;/em&gt; pair for &lt;em&gt;Encrypting&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;When &lt;em&gt;addkey&lt;/em&gt;, a new subkey pair will be generated.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Each subkey pair can be identified by hexadecimal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--fingerprint --fingerprint&lt;/code&gt;, &lt;em&gt;keyid&lt;/em&gt; (low 64 bits of &lt;em&gt;fingerprint&lt;/em&gt;), &lt;em&gt;uid&lt;/em&gt;, email address, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;openssh&quot;&gt;OpenSSH&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Check key information by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-keygen -lv&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-add -l&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Use &lt;em&gt;ssh-copy-id&lt;/em&gt; to distribute public key to remote server. It simply appends the public key file contents to remote &lt;em&gt;~/.ssh/authorized_keys&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;SSH key does NOT hold &lt;em&gt;uid&lt;/em&gt;. On the contrary, email and notes are called &lt;em&gt;comments&lt;/em&gt; which can be changed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-keygen [-o] -c&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>avplayer.org</title>
   <link href="/2017/03/09/avplayer/"/>
   <updated>2017-03-09T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/03/09/avplayer</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;Powered by &lt;a href=&quot;https://github.com/jgm/gitit&quot;&gt;gitit&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Update procedure:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ssh-add&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ssh fyzhuji&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cd /srv/wiki/wikidata&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# edit my.file&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# git add my.file&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# git commit -m &quot;edit my file&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;That&apos;s all! No need to push since updating on server.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>CN2 VPS</title>
   <link href="/2017/02/16/cn2-vps/"/>
   <updated>2017-02-16T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/02/16/cn2-vps</id>
   <content type="html">&lt;h1 id=&quot;virtualization&quot;&gt;Virtualization&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;OpenVZ/XEN/KVM&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;openvz&quot;&gt;OpenVZ&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;OpenVZ is a half virtualized technology at OS-level with limitations. Each VPS is actually a guest operating system &lt;em&gt;container&lt;/em&gt; and shares the same underlying host operating system but still operates as secure, isolated environment.
    &lt;ol&gt;
      &lt;li&gt;We cannot make any kernel level modifications inside the VPS. The VPS&apos;s on the host share the host kernel.&lt;/li&gt;
      &lt;li&gt;Host can easily be over-subscribed. Hosting providers can and do host 20+ OpenVZ virtual machines on a system with 12 GB of ram. Each VPS has 1 GB of ram &quot;assigned&quot; to it. Not all systems use 1 GB all the time, so the system &quot;robs Peter to pay Paul&quot; when a VPS does need all its memory. It will allow the VPS to access its assigned amount of ram. However if none is available due to other VPS&apos;s using it, contention can get bad and things slow down.&lt;/li&gt;
      &lt;li&gt;Openvz is better when you want to run a mass of linux VMs and need to be able to flexibly allocate resources between them. Since the systems are all using the same file system, kernel and memory space, a container dosen&apos;t need memory for its exclusive use.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;xen&quot;&gt;XEN&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;OpenVZ is generally oversells to take advantages of unused resources, while XEN cannot, thus slightly more costly and they call XEN VDS (Virtual Dedicated Server) rather than VPS (Virtual Private Server). If you running gameserver for example, XEN is a MUST! KVM won&apos;t be as fast as XEN.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;kvm&quot;&gt;KVM&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Your host OS has to be Linux but it supports Linux, Windows, Solaris, and BSD guests. It runs on x86 and x86-64 systems with hardware supporting virtualization extensions (Intel VT or AMD-V). It consists of a loadable kernel module, that provides the core virtualization infrastructure and a processor specific module.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;chinatelecom-163-to-cn2&quot;&gt;ChinaTelecom 163 to &lt;a href=&quot;https://www.gubo.org/instroduction-to-cn2-and-cn2-vps-providers/?PageSpeed=noscript&quot;&gt;CN2&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;ChinaNetNextCarryingNetwork (CN2)&lt;/p&gt;

    &lt;p&gt;Isolated from the old ChinaNet/China163, CN2 is ChinaTelecom&apos;s newly built highly qualified backbone to serve coporate clients.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.linode.com/docs/networking/diagnostics/diagnosing-network-issues-with-mtr&quot;&gt;MTR&lt;/a&gt; - My TraceRoute, an Excellent network diagnostic tool&lt;/p&gt;

    &lt;p&gt;MTR represents an evolution of &lt;em&gt;traceroute&lt;/em&gt; with a greate data sample. It combines the functions of the traceroute and ping programs in one network diagnostic tool.&lt;/p&gt;

    &lt;p&gt;Because MTR provides an image of the route traffic takes from one host to another, you can think of it as a &lt;em&gt;directional&lt;/em&gt; tool. Furthermore, the route taken between two points on the Internet can vary a great deal based on location and the routers that are located upstream of you. For this reason it is often recommended that you collect MTR reports in &lt;em&gt;both directions&lt;/em&gt; for all hosts that are experiencing connectivity issues, or as many hosts as possible.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mtr &lt;span class=&quot;nt&quot;&gt;-rtw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;destination_host]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Bi-directional CN2&lt;/p&gt;

    &lt;p&gt;It&apos;s really important to &lt;em&gt;mtr&lt;/em&gt; from VPS to PC since that&apos;s the daily traffic flow direction!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;An example of &lt;em&gt;mtr&lt;/em&gt; output:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;zhtux ~ # mtr -rw 220.173.118.215
Start: Thu Feb 16 20:25:53 2017
HOST: zhtux           Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 192.168.0.1      0.0%    10    3.0   2.1   1.1   6.2   1.5
  2.|-- hz-dns90         0.0%    10    4.8   4.0   2.5   7.5   1.3
  3.|-- 172.16.203.253   0.0%    10    3.9   4.5   3.5   6.4   0.8
  4.|-- hz-dns90         0.0%    10    3.7   3.8   1.9   8.1   2.1
  5.|-- hz-dns90         0.0%    10    6.0  12.1   5.2  40.8  10.8
  6.|-- hz-dns90        20.0%    10   23.7   8.6   3.0  23.7   6.9
  7.|-- 101.4.114.229   50.0%    10    6.0  15.6   6.0  32.9  10.7
  8.|-- 101.4.112.37     0.0%    10   26.2  31.1  23.3  59.3  10.2
  9.|-- 101.4.117.34    10.0%    10   18.8  27.8  18.8  43.9   8.6
 10.|-- 101.4.118.154    0.0%    10   20.6  25.5  20.6  34.4   4.5
 11.|-- 202.97.15.237    0.0%    10   57.1  58.5  43.7  72.2  10.7
 12.|-- 202.97.46.109   60.0%    10   84.3  81.8  73.0  92.3   8.4
 13.|-- 202.97.77.30    60.0%    10  101.2  92.6  84.5 101.2   7.8
 14.|-- ???             100.0    10    0.0   0.0   0.0   0.0   0.0
 15.|-- 220.173.118.215  0.0%    10   97.3  95.9  84.1 105.3   7.9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;If a node has 100% loss rate, it probably disallows &lt;em&gt;ping&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Usually, IP nodes beginning with &lt;em&gt;59.43&lt;/em&gt; represents CN2 line.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Mobile Phone specifications</title>
   <link href="/2017/02/05/cell-phone/"/>
   <updated>2017-02-05T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/02/05/cell-phone</id>
   <content type="html">&lt;p&gt;Gonna buy a mobile phone? Ha, you are probably trapped by vendor &lt;em&gt;inspiring&lt;/em&gt; presenation! What invented you are not the reality. To pick up a reasonable mobile phone, please examinate specifications.&lt;/p&gt;

&lt;h1 id=&quot;summary&quot;&gt;Summary&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Hardware is not everything!&lt;/p&gt;

    &lt;p&gt;iPhones&apos; is relativly inferior to counterparts but the outcome is better.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;You&apos;d best buy a black version to hide &lt;em&gt;black margin&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Phone at a discount might be &lt;em&gt;substantially repaired&lt;/em&gt; ones.&lt;/li&gt;
  &lt;li&gt;Though most phones are produced by FOXCONN, final qualification determined by meta equipment, quality control, design etc.&lt;/li&gt;
  &lt;li&gt;Huawei&apos;s operating system is designed to prevent users from &lt;em&gt;rooting&lt;/em&gt;! Think twice before upgrading.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Vivo/Oppo does not deserve the price.&lt;/p&gt;

    &lt;p&gt;Vivo/Oppo/OnePlus share the owner. Oneplus focuses on users overseas.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;chipsetsoc&quot;&gt;Chipset/SoC&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;SoC consists of CPU, GPU, &lt;a href=&quot;https://www.zhihu.com/question/25579096&quot;&gt;Baseband processor&lt;/a&gt; (BP, BBP) etc, of which BP is the most &lt;a href=&quot;https://www.zhihu.com/question/31765069&quot;&gt;paramount&lt;/a&gt;, responsible for telecommunication.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Qualcomm Snapdragon (CPU) is better than MediaTek (MTK) Helio.&lt;/p&gt;

    &lt;p&gt;Most processor vendors develop both CPUs and GPUs and tend to combine their own CPU/GPU in chipset (SoC). For example, Snapdragon CPUs are usually accompanied by Qualcomm Adreno GPU.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;CPU model outshines number of Cores.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Pay attention to frequency, i.e. Snapdragon 820 1.8GHz VS 2.15GHz.&lt;/p&gt;

    &lt;p&gt;Each core may differ in frequency, say 6 cores of 1.5GHz while 2 another of 2.00GHz.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;14nm/20nm.&lt;/li&gt;
  &lt;li&gt;GPU
    &lt;ol&gt;
      &lt;li&gt;Qualcomm Adreno (embeded into Qualcomm SoC);&lt;/li&gt;
      &lt;li&gt;ARM Mali;&lt;/li&gt;
      &lt;li&gt;PowerVR SGX (used by many Apple product);&lt;/li&gt;
      &lt;li&gt;NVIDIA Tegra;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;BP is built-in or external? Support LTE user equipment category 6 (CAT6) / CAT7?&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ramrom&quot;&gt;RAM/ROM&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;RAM - memory.
    &lt;ol&gt;
      &lt;li&gt;LPDDR3/4&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;ROM - flash disk where OS resides.
    &lt;ol&gt;
      &lt;li&gt;eMMc5.0/5.1/UFS 2.0/UFS 2.1&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;micro-SD card extension.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;battery&quot;&gt;Battery&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Charger. QC3.0/2.0/VOOC&lt;/li&gt;
  &lt;li&gt;1/2/3A&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;wireless&quot;&gt;Wireless&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;80211b/a/g/n/ac wave1/ac wave2 (2-stream mu-mimo).&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;camera&quot;&gt;Camera&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;f/1.8, 2.0, 2.2&lt;/li&gt;
  &lt;li&gt;Optical Image Stabilization (OIS)&lt;/li&gt;
  &lt;li&gt;Phase Detection Auto Focus (PDAF)&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;sensor&quot;&gt;Sensor&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;NFC&lt;/li&gt;
  &lt;li&gt;Ultra-red&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;socket&quot;&gt;Socket&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Type-C USB 2.0/3.0/3.1&lt;/li&gt;
  &lt;li&gt;OTG&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>GTK recently-used.xbel</title>
   <link href="/2017/01/23/gtk-recently-used-xbel/"/>
   <updated>2017-01-23T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/01/23/gtk-recently-used-xbel</id>
   <content type="html">&lt;p&gt;GTK2/3 library creates &lt;em&gt;~/.local/share/recently-used.xbel&lt;/em&gt; for applications to keep their recently visited files, revealing user privacy! To disable &lt;em&gt;recently-used.xbel&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Create directory with the same name.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; .local/share/recently-used.xbel&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; .local/share/recently-used.xbel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This is enough! The next configurations are alternatives by changing GTK2/3 configurations.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;GTK3 &lt;em&gt;setting.ini&lt;/em&gt;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[Settings]&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;gtk-recent-files-max-age=0&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;gtk-recent-files-limit=0&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.config/gtk-3.0/settings.ini
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;GTK2 &lt;em&gt;gtkrc-2.0&lt;/em&gt;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;gtk-recent-files-max-age=0&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.gtkrc-2.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Refs:&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;https://alexcabal.com/disabling-gnomes-recently-used-file-list-the-better-way/&quot;&gt;disabling-gnomes-recently-used-file-list-the-better-way&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://askubuntu.com/a/269874&quot;&gt;How do I prevent the file &apos;recently-used.xbel&apos; from being created&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/GTK%2B#Configuration&quot;&gt;GTK configuration&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Thinkpad X220 upgrading</title>
   <link href="/2017/01/12/x220-upgrade/"/>
   <updated>2017-01-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2017/01/12/x220-upgrade</id>
   <content type="html">&lt;p&gt;Thinkpad X220 is somewhat &lt;em&gt;ancient&lt;/em&gt;, purchased in 2012. I am gonna improve &lt;em&gt;memory&lt;/em&gt; and &lt;em&gt;disk&lt;/em&gt;. There is a variety of different memory and disk alternatives. Before payment, think twice!&lt;/p&gt;

&lt;h1 id=&quot;specs&quot;&gt;Specs&lt;/h1&gt;

&lt;p&gt;Model: 4290NL7
ISA bridge: QM67&lt;/p&gt;

&lt;h2 id=&quot;memory&quot;&gt;Memory&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;4GB (1*4GB), 8GB max&lt;/li&gt;
  &lt;li&gt;PC3-10600 1333MHz DDR3 SDRAM&lt;/li&gt;
  &lt;li&gt;Base sizes: 1GB, 2GB, 4GB&lt;/li&gt;
  &lt;li&gt;Non-parity&lt;/li&gt;
  &lt;li&gt;Dual-channel capable&lt;/li&gt;
  &lt;li&gt;Two 204-pin SO-DIMM sockets&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;disk&quot;&gt;Disk&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Primary Drive Bay: 2.5&quot; wide, 7mm high, SATA3 or SSD.&lt;/p&gt;

    &lt;p&gt;Shipped with SATA2 320GB/7200rpm disk.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;mSATA Slot: SATA2, compatible with all newer mSATA SSDs.&lt;/li&gt;
  &lt;li&gt;SATA2: 3Gbps; SATA3: 6Gbps.&lt;/li&gt;
  &lt;li&gt;The 2.5-inch bay can take slim 7mm hard drives and SSDs while the mSATA slot, located under the keyboard, can only take specialized mSATA SSDs.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Wireless PCI Express Mini Card for WWAN shares the same motherboard slot on board. They cannot be used simultaneously - sSATA or WWAN.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;mSATA derived from mPCIe (mini PCI express) is an obsolete standard. System made after 2012 does not use neither of them any more. M.2 is the newer replacement.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;static-electricity-prevention&quot;&gt;Static electricity prevention&lt;/h1&gt;

&lt;p&gt;Static electricity, although harmless to you, can seriously damage computer components and options. Improper handling of static-sensitive parts can cause damage to the part.&lt;/p&gt;

&lt;p&gt;Touch a metal table or a grounded metal object (i.e. faucet). This action reduces any static electricity from your body. The static electricity could damage the card.&lt;/p&gt;

&lt;h1 id=&quot;upgrading&quot;&gt;Upgrading&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Memory&lt;/p&gt;

    &lt;p&gt;A new 4GB strip.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Disk&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Though SATA2 is almost half the speed of SATA3, it does NOT make much difference to daily operation without intensive I/O.&lt;/li&gt;
      &lt;li&gt;New &lt;em&gt;cheap&lt;/em&gt; mSATA SSD now that &lt;em&gt;expensive&lt;/em&gt; one cannot be fully exploited due to SATA2 limitation. What&apos;s more, SSD is not for data storage.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ssd&quot;&gt;&lt;a href=&quot;https://www.zhihu.com/question/20369676&quot;&gt;SSD&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;4k alignment;&lt;/li&gt;
  &lt;li&gt;4k random read/write performance (IOPS) is critical performance reference;&lt;/li&gt;
  &lt;li&gt;Check SMART data by official tool or CrystalDiskInfo;&lt;/li&gt;
  &lt;li&gt;Turn on AHCI in BIOS;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Theme</title>
   <link href="/2016/11/23/theme/"/>
   <updated>2016-11-23T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/11/23/theme</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#scheme&quot; id=&quot;markdown-toc-scheme&quot;&gt;Scheme&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#xfce&quot; id=&quot;markdown-toc-xfce&quot;&gt;Xfce&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#guake&quot; id=&quot;markdown-toc-guake&quot;&gt;Guake&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#emacs&quot; id=&quot;markdown-toc-emacs&quot;&gt;Emacs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;scheme&quot;&gt;Scheme&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/lassekongo83/zuki-themes/tree/3.20&quot;&gt;x11-themes/zuki-themes-3.20&lt;/a&gt; is compatible with both GTK2 and GTK3.
    &lt;ol&gt;
      &lt;li&gt;Make sure &lt;em&gt;xfce&lt;/em&gt; USE is enabled to include relevant Xfwm4 part.&lt;/li&gt;
      &lt;li&gt;(opt) Get a copy of &lt;em&gt;chrome/userChrome.css&lt;/em&gt; into Firefox&apos;s profile like &lt;em&gt;~/.mozilla/firefox/53rwll2m.default/chrome/userChrome.css&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/PapirusDevelopmentTeam/papirus-icon-theme&quot;&gt;papirus-icon-theme&lt;/a&gt; for Icons. The advantage of &lt;em&gt;papirus-icon-theme&lt;/em&gt; is supporting &lt;em&gt;hardcode-tray&lt;/em&gt; support, especially for Thunar icons.&lt;/p&gt;

    &lt;p&gt;Just copy Papirus and Papirus-Dark to &lt;em&gt;~/.local/share/icons/&lt;/em&gt;. Remember to &lt;em&gt;gtk-update-icon-cache ~/.loca/share/icons/{Papirus,Papirus-Dark}&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://ethanschoonover.com/solarized&quot;&gt;Solarized&lt;/a&gt; is a &lt;em&gt;palette&lt;/em&gt; theme mainly for editor (Emacs/Vim) and &lt;a href=&quot;http://www.wanglifeng.info/sysadmin/solarized-color-scheme.html&quot;&gt;terminal emulator&lt;/a&gt; (&lt;a href=&quot;https://github.com/Guake/guake&quot;&gt;Guake&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;xfce&quot;&gt;Xfce&lt;/h1&gt;

&lt;p&gt;Theme are &lt;a href=&quot;https://forum.xfce.org/viewtopic.php?id=8787&quot;&gt;divided&lt;/a&gt; into &lt;a href=&quot;https://wiki.xfce.org/howto/install_new_themes&quot;&gt;5 different themes&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;GTK2/3 theme: Applications/Settings/Apperance/Style. Rendering GTK &lt;em&gt;toolkit&lt;/em&gt; like buttons, textboxes, drawing canvas, etc - everything &lt;em&gt;within&lt;/em&gt; the border and title bar of a window.&lt;/li&gt;
  &lt;li&gt;Window Manager theme (Xfwm4): Applications/Settings/Window Manager/Style. The borders, title bar, maximize/minimize buttons, etc.&lt;/li&gt;
  &lt;li&gt;Icon theme (Adwaita): Applications/Settings/Apperance/Icons.&lt;/li&gt;
  &lt;li&gt;Notification theme: Applications/Settings/Notifications. Notification popup.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Cursor theme:  Applications/Settings/Mouse and Touchpad/Theme.&lt;/p&gt;

    &lt;p&gt;All of these components play a part in determining the &lt;em&gt;look&lt;/em&gt; of Xfce Desktop as you see it on the screen.&lt;/p&gt;

    &lt;p&gt;Check &lt;em&gt;/usr/share/themes&lt;/em&gt; and &lt;em&gt;/usr/share/icons&lt;/em&gt; for theme files.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Themes can be configured by command &lt;em&gt;gconftool-2&lt;/em&gt; either.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(deprecated) Consistent look for GTK2 and GTK3.&lt;/p&gt;

    &lt;p&gt;By default, &lt;em&gt;x11-themes/gtk-engines-xfce:0&lt;/em&gt; (slot 0 for GTK2 themes) is installed. We emerge it explicitly to pull in GTK3 themes (slot 3).&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt x11-themes/gtk-engines-xfce&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Term &lt;em&gt;theme engine&lt;/em&gt; refers to preliminary themes that mainly serve as dependencies of other themes. For example, many excel themes (i.e. Arc-theme and Greybird) depend on &lt;em&gt;gtk-engines-murrine&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;The xfce devs dropped support for gtk3-themes in the &lt;em&gt;default theme&lt;/em&gt; (&lt;em&gt;gtk-engines-xfce&lt;/em&gt;), because the theming api broke so much in the releases that they couldn&apos;t keep the pace. now it&apos;s the job of the distributor to provide a common theme&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Rude GTK3&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;GTK3 updates always break existing themes. The developers just ignore themes compatibility!&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;&lt;em&gt;&amp;gt;=x11-libs/gtk+-3.20&lt;/em&gt; breaks existing Xfce GTK3 themes (i.e. Firefox mouseover fails to display, scroolbar disappers, Ctrl-o no borders etc.).&lt;/p&gt;

    &lt;p&gt;Since many packages depend on 3.20, we have to either choose a compatible GTK3 theme (i.e. &lt;a href=&quot;https://wiki.gentoo.org/wiki/Xfce#Greybird_theme&quot;&gt;Greybird&lt;/a&gt; require many dependencies) or remove GTK3 theme from system (only slot 0). What&apos;s worse, Xfce&apos;s default GTK2 Raleigh theme is incompatible with some GTK3 applications.&lt;/p&gt;

    &lt;p&gt;Themes should be updated regularly to remain compatible with the GTK3 library installed on system.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Zuki - a GTK3-compatible theme&lt;/p&gt;

    &lt;p&gt;To &lt;a href=&quot;https://wiki.xfce.org/howto/install_new_themes&quot;&gt;manually configure&lt;/a&gt; consistent desktop look, choose a theme that covers as many aspects of those five categories as possible, cares about GTK version 2 and 3, and updates frequently to follow GTK3 library.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(deprecated) Missing icons&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;xfce-base/xfce4-meta&lt;/em&gt; depends on &lt;em&gt;virtual/freedesktop-icon-theme&lt;/em&gt;. The lastest &lt;em&gt;virtual/freedesktop-icon-theme&lt;/em&gt; ebuild has been changed to prefer &lt;em&gt;x11-themes/adwaita-icon-theme&lt;/em&gt; (by default) over &lt;em&gt;x11-themes/gnome-icon-theme&lt;/em&gt;. But the former does not contain icons for Xfce4 Desktop.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avtn x11-themes/gnome-icon-theme&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Since &lt;em&gt;papirus-icon-theme&lt;/em&gt; is used, we leave Xfce&apos;s default icon themes alone.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;guake&quot;&gt;Guake&lt;/h1&gt;

&lt;p&gt;Without explicit note, I use &lt;em&gt;terminal&lt;/em&gt; and &lt;em&gt;terminal emulator&lt;/em&gt; interchangeably.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Palette
    &lt;ol&gt;
      &lt;li&gt;Most terminals support palette setting in &lt;em&gt;Preferences/Appearance&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;If the built-in palette fails to meet your requirement, try separate palette manually like &lt;a href=&quot;https://github.com/coolwanglu/guake-colors-solarized&quot;&gt;guake-colors-solarized&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;Usually, choose &lt;em&gt;solarized-dark&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;TERM&lt;/p&gt;

    &lt;p&gt;Applications (Emacs Vim etc.) to run in terminal may depend on variable TERM to correctly apply palette.&lt;/p&gt;

    &lt;p&gt;Guake supports 256 colors (ancient terminals have only 16 colors). However due to this bug &lt;a href=&quot;https://github.com/Guake/guake/issues/772&quot;&gt;support true colors in terminal&lt;/a&gt;, Guake fails to set TERM (&lt;em&gt;xterm&lt;/em&gt;) as &lt;em&gt;xterm-256color&lt;/em&gt;. This can be verified by &lt;em&gt;tput colors&lt;/em&gt; (8 foreground colors and 8 background colors) and &lt;em&gt;M-x: list-colors-display&lt;/em&gt; in Emacs.&lt;/p&gt;

    &lt;p&gt;It&apos;s terminal emulator&apos;s job to set TERM on startup before any shell init scripts are loaded. But before the bug is resolved, we must resort to shell.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ~/.bashrc&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; /usr/share/terminfo/x/xterm-256color &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$TERM&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;rxvt-unicode|screen|tmux|xterm&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TERM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TERM&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-256color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Possible TERM values can be found unser &lt;em&gt;/usr/share/terminfo&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/seebi/dircolors-solarized&quot;&gt;dircolors-solarized&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;After changing to &lt;em&gt;solarized-dark&lt;/em&gt; palette, &lt;em&gt;ls&lt;/em&gt; output displays ugly. To fix that, apply Solarized color setup to &lt;em&gt;ls&lt;/em&gt; output by &lt;em&gt;dircolors&lt;/em&gt; - solarized palette for &lt;em&gt;ls&lt;/em&gt; command.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/opt
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 https://github.com/seebi/dircolors-solarized
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sv&lt;/span&gt; ~/opt/dircolors-solarized/dircolors.ansi-dark ~/.dircolors
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;eval `dircolors ~/.dircolors`&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;c&quot;&gt;# Uncheck *Allow bold font* in Preferences&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;There are four available color theme, namely &lt;em&gt;dircolors.{256dark,ansi-universal,ansi-dark,ansi-light}&lt;/em&gt;.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;If the terminal does not support Solarized palette (rarely), choose &lt;em&gt;dircolors.256color&lt;/em&gt; which simulates Solarized by terminal&apos;s built-in 256 colors, resulting in an &lt;em&gt;approximate&lt;/em&gt; Solarized theme. It must be a 256-color terminal and TERM is correctly set.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;dircolors.ansi-universal&lt;/em&gt; is smart enough to work both for 16 colors and 256 colors.&lt;/li&gt;
      &lt;li&gt;If you are sure about the terminal colors, choose &lt;em&gt;dircolors.ansi-{dark,light}&lt;/em&gt;. They are optimized version.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Summary
    &lt;ol&gt;
      &lt;li&gt;Guake has 256 colors;&lt;/li&gt;
      &lt;li&gt;Wrong TERM value due to bug (updated in &lt;em&gt;~/.bashrc&lt;/em&gt;);&lt;/li&gt;
      &lt;li&gt;Support Solarized palette in Preferences;&lt;/li&gt;
      &lt;li&gt;Choose &lt;em&gt;dircolors.ansi-{dark,light}&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;emacs&quot;&gt;Emacs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/sellout/emacs-color-theme-solarized&quot;&gt;emacs-color-theme-solarized&lt;/a&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ $ cd ~/.emacs.d/site-lisp
~ $ git clone --depth=1 https://github.com/sellout/emacs-color-theme-solarized
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Loading&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;custom-theme-load-path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;site-lisp/emacs-color-theme-solarized&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user-emacs-directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; By default it&apos;s 16, but requires terminal emulator palette set to `solarized&apos; and&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; make sure `TERM={xterm,screen,rxvt-unicode}-256color&apos;. Otherwsie set to&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; 256 and got degraded but approximate `solarized&apos; theme&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;(setq solarized-termcolors 256)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-theme&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;solarized&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; `solarized-light&apos; in GUI mode; `solarized-dark&apos; in terminal&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;after-make-frame-functions&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;display-graphic-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;light&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set-frame-parameter&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;background-mode&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set-terminal-parameter&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;background-mode&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;enable-theme&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;solarized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Fix&lt;/p&gt;

    &lt;p&gt;Currently, there is a &lt;a href=&quot;https://github.com/bbatsov/solarized-emacs/issues/18&quot;&gt;6-year bug&lt;/a&gt; not yet fixed, namely Emacs solarized in terminal with true 256 color is not correctly displayed.&lt;/p&gt;

    &lt;p&gt;If you encounter such issue, either strip &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-256color&lt;/code&gt; from TERM value or set &lt;em&gt;(setq solarized-termcolors 256)&lt;/em&gt; in &lt;em&gt;init.el&lt;/em&gt;. We can also set individual TERM value for Emacs like this:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;TERM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TERM&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%-256color&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; emacsclient &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;No matter which method is chosen, we have to degrade to 8-bit color in terminal before the bug is fixed!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Encoding</title>
   <link href="/2016/11/22/encoding/"/>
   <updated>2016-11-22T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/11/22/encoding</id>
   <content type="html">&lt;h1 id=&quot;terminology&quot;&gt;Terminology&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Code point: the raw code defined by people (Unicode, 区位码).&lt;/li&gt;
  &lt;li&gt;Cdoe unit: code after encoding.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Fixed witdth/length encoding: without transformation. Code points are directly indexable. Finding the Nth code point in a sequence of code points is a constant time operation.&lt;/p&gt;

    &lt;p&gt;For example. read two bytes each time.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Variable width/length encoding: MUST has transformation. Efficient space usage .&lt;/p&gt;

    &lt;p&gt;Read byte by byte.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Big/Little Endian (BE/LE):
    &lt;ol&gt;
      &lt;li&gt;Decides whether the bigger part (MSB, high bytes) or little part (low bytes) is stored &lt;em&gt;first&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Firstly stored bytes actually resides on low disk/memory address.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Byte order mark (BOM). Depending on BE or LE, a byte read may represent different characters. BOM is inserted into the very beginning to differentiate BE and LE.
    &lt;ol&gt;
      &lt;li&gt;UTF-8: EF BB FF. BOM is not a must, but help mark it&apos;s UTF-8.&lt;/li&gt;
      &lt;li&gt;UTF-16/UCS-2 BE: FE FF.&lt;/li&gt;
      &lt;li&gt;UTF-16/UCS-2 LE: FF FE.&lt;/li&gt;
      &lt;li&gt;UTF-32/UCS-4 BE: 00 00 FE FF　　&lt;/li&gt;
      &lt;li&gt;UTF-32/UCS-4 LE: FF FE 00 00&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;unicodeucs&quot;&gt;Unicode/UCS&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;At the very beginning, there were two independent institutes deciding to desgin a international coding system, namely ISO (ISO 10646 project, UCS) and &lt;em&gt;unicode.org&lt;/em&gt; (Unicode). Finally they together merged their desgin and chosen Unicode as the scheme name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;16 planes: U+0000 ~ U+10FFFF, at most 21 bits.&lt;/li&gt;
  &lt;li&gt;Basic Multilingual Plane (BMP): U+0000 ~ U+FFFF.&lt;/li&gt;
  &lt;li&gt;Includes almost all possible characters in the world.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;utf-16-vs-ucs-2&quot;&gt;UTF-16 vs. UCS-2&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;UTF-16 is downward compatibility with UCS-2.&lt;/li&gt;
  &lt;li&gt;UCS-2 is fixed width (16 bits) &lt;em&gt;encoding scheme&lt;/em&gt; while the successor UTF-16 is variable width (sequence of 16-bit words).&lt;/li&gt;
  &lt;li&gt;UCS-2 covers code points in BMP from U+0000 to U+FFFF with any &lt;em&gt;transformation&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Apart from the BMP, UTF-16 covers other planes with the help of &lt;em&gt;surrogate code points&lt;/em&gt; (from U+D800 - U+DFFF) and results in a pair of 16-bit words, together called &lt;em&gt;surrogate pair&lt;/em&gt;.
    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;surrogate code point&lt;/em&gt; in Unicode has no corresponding characters. They are for furture extension.&lt;/li&gt;
      &lt;li&gt;So UTF-16 covers all Unicode planes from U+0000 to U+10FFFF with ether one 16-bit word or a pair of 16-bit word.&lt;/li&gt;
      &lt;li&gt;For BMP, Unicode = UCS-2 = UTF-16 (code point = code unit).&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;To decode a UTF-16/UCS-2 code unit, read two bytes or four bytes. One byte or three bytes is meaningless.&lt;/li&gt;
  &lt;li&gt;UCS-2 is obsolete.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;utf-32ucs-4&quot;&gt;UTF-32/UCS-4&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;UTF-32 and UCS-4 is identical.&lt;/li&gt;
  &lt;li&gt;Fixed-length encoding with exactly 32 bits. There are many leading zero bits.&lt;/li&gt;
  &lt;li&gt;Without any transformation. Each 32-bit value in UTF-32 represents one Unicode code point and is exactly equal to that code point&apos;s numerical value.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ansi&quot;&gt;ANSI&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;You may encounter it in Windows.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It&apos;s not a concrete encoding, but scheme used Windows to select the correct encoding which is transparent to users.&lt;/p&gt;

    &lt;p&gt;If the Windows system is English, then the encoding behind is codepage &lt;em&gt;cp437&lt;/em&gt;, while Chinese corresponds to &lt;em&gt;cp936&lt;/em&gt; (namely GBK).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;国家标准信息交换用汉字编码简称国标码gb2312-80标准&quot;&gt;国家标准信息交换用汉字编码，简称国标码（GB2312-80标准）&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;所有的汉字编码都兼容ASCII。更多细节参考&lt;a href=&quot;http://bbs.csdn.net/topics/370146113&quot;&gt;外码？内码？&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;区位码：把汉字列成一94行94列的表，每行称区，每列称位。区位座标定位一个汉字，如“汉”的区位码是十进制2626，十六进制1A1AH，表示“汉”在表格的第26行第26列。
    &lt;ol&gt;
      &lt;li&gt;区位码是编码设计的草稿。默认用十进制表示。&lt;/li&gt;
      &lt;li&gt;2字节表示一个汉字。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;国标码：区位码+2020H，得到国家标准编码GB2312（GB表示“国标”）.“汉”的GB2312码是1A1AH+2020H=3A3AH.&lt;/p&gt;

    &lt;p&gt;国标码是国家标准，不可乱改。注意，这里国标码最高位是0.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;GB2312区位码和国标码都是人认识的编码，计算机是不知道的，通常称之为“（机）外码”。&lt;/p&gt;

    &lt;p&gt;字面意思是在计算外实用的码。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;（机）内码：国标码+8080H或区位码+A0A0H，得到汉字在计算机内存储的编码。“汉”的机内码是3A3AH+8080H=BABAH.&lt;/p&gt;

    &lt;p&gt;把国标码的最高位置1，即得到机内码。ASCII字节最高位为0，计算机很容易区分汉字和英语。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;计算机存储的是GB2312的机内码，而不是国标码。这与ASCII、UTF-8等直接存储编码不同。&lt;/li&gt;
  &lt;li&gt;Unicode和国标码不兼容，具体说是Unicode的code point和GB2312国标码之间没有换算关系。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;gbk-gb18030&quot;&gt;GBK GB18030&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;GB2312的扩展，GB2312、GBK（K表示“扩展”）到GB18030向下兼容。&lt;/li&gt;
  &lt;li&gt;不同之处：
    &lt;ol&gt;
      &lt;li&gt;后面的包含更多的汉字；&lt;/li&gt;
      &lt;li&gt;GBK GB18030只要求机内码第一字节开头置1（只有第一字节加80H），但兼容部分国标码两字节都必须是1开头。这不影响对GBK、GB18030的解码，只要遇到开头是1的，就接着都下一字节，合并解码。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;从GBK、GB18030开始，机内码就是国标码，不需要什么区位码、国标码、到机内码转换。&lt;/p&gt;

    &lt;p&gt;所以通常叫GB2312为区位码，GBK为机内码，以示这个微妙地区分。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;现在的PC平台必须支持GB18030，对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。&lt;/li&gt;
  &lt;li&gt;从编程角度看，GB2312、GBK到GB18030都属于“双字节字符集” (DBCS)，并且都是大端先存（BE）。属于Fixed Width Encoding的一种.&lt;/li&gt;
  &lt;li&gt;中文Windows的缺省内码是GBK，可以通过GB18030升级包升级到GB18030。不过GB18030相对GBK增加的字符，普通人很难用到，通常我们还是用GBK指代中文Windows内码。&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Filesystem</title>
   <link href="/2016/11/20/filesystem/"/>
   <updated>2016-11-20T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/11/20/filesystem</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post talks about filesystem operations under Linux environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;filesystem&quot;&gt;Filesystem&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Filename is a string encoded and stored in fileystem.&lt;/li&gt;
  &lt;li&gt;Linux kernel first decodes filename stored on disk (more specific, in filesystem on disk), then encodes it again, and finally submit to user space applications (like &lt;em&gt;ls&lt;/em&gt;, &lt;em&gt;thuar&lt;/em&gt; etc.).&lt;/li&gt;
  &lt;li&gt;When it comes to reading filenames on disk,
    &lt;ol&gt;
      &lt;li&gt;Windows NT kernel reads two bytes at a time. Everything in Windows NT kernel is UCS-2.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Linux kernel reads byte by byte, which means it recoginizes only variable length encoding streams, single byte encoding (i.e. cp437) included.&lt;/p&gt;

        &lt;p&gt;The possible encoding streams are listed in Native Language Support (NLS) under File Systems in &lt;em&gt;make menuconfig&lt;/em&gt;. But be careful, this NLS (in kernel space) is different from that one (&lt;em&gt;nls&lt;/em&gt; USE and sytem &lt;em&gt;locale&lt;/em&gt;) in user space.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;fat&quot;&gt;FAT&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;FAT is not a separate filesystem, but a common part of the &lt;a href=&quot;https://en.wikipedia.org/wiki/FAT_filesystem_and_Linux&quot;&gt;MSDOS, UMSDOS and VFAT&lt;/a&gt;.
    &lt;ol&gt;
      &lt;li&gt;Mount options of FAT applies to MSDOS, UMSDOS and VFAT either.&lt;/li&gt;
      &lt;li&gt;Attention, they are Linux filesystem drivers, not the original Windows FAT filesystems.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;You might encounter two confusing options namely &lt;em&gt;codepage&lt;/em&gt; and &lt;em&gt;iocharset&lt;/em&gt;. Without proper setting, you would see garbled filenames.
    &lt;ol&gt;
      &lt;li&gt;To be simple, &lt;em&gt;codepage&lt;/em&gt; encodes (on creation) and decodes (on display) &lt;em&gt;shortname&lt;/em&gt; while &lt;em&gt;iocharset&lt;/em&gt; should be the system &lt;em&gt;locale&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;No matter of &lt;em&gt;codepage&lt;/em&gt; or &lt;em&gt;iocharset&lt;/em&gt;, it&apos;s used by kernel instead of application.&lt;/li&gt;
      &lt;li&gt;The &lt;em&gt;codepage&lt;/em&gt; for display should be the same as that of creation, otherwise it&apos;s decoded as garbage.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Details are a long story as follows:&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;shortname-and-longname&quot;&gt;shortname and longname&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Shortname is a concept belongs to MSDOS only.
    &lt;ol&gt;
      &lt;li&gt;Looks like &lt;em&gt;8.3&lt;/em&gt;. The former is at most 8-byte long and the extension occupies 3 bytes.&lt;/li&gt;
      &lt;li&gt;Case insensitive. Actually only allow upper case characters.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Upon VFAT, long filename is supported, abandoning that two limitations.&lt;/p&gt;

    &lt;p&gt;In order to be compatible with MSDOS, each filename has a shortname version. We call the original one as longname. That is to say, VFAT stores two filenames in filesystem like:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;longname; shortname, codepage&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Shortname is encoded as &lt;em&gt;codepage&lt;/em&gt; (i.e. 936 for Simplified Chinese), while longname is encoded as Unicode (NOT UTF-8).&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Actually, most modern fileystems encode filenames as Unicode.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;mount&quot;&gt;Mount&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;When it comes to &lt;em&gt;mount&lt;/em&gt;, we talk about &lt;em&gt;mounting FAT (MSDOS VFAT) under Linux&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;codepage&lt;/em&gt; option. Kernel uses it to decode shortname and then translates it into Unicode. Longname is Unicode by default.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;iocharset&lt;/em&gt; option. Kernel uses it to encode the Unicode shortname (MSDOS) or longname (VFAT). Then the encoded stream is passed to use space.&lt;/p&gt;

    &lt;p&gt;There is a special &lt;em&gt;iocharset&lt;/em&gt; value &lt;em&gt;utf8&lt;/em&gt;. You should set it in a separate way (discussed next).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Upon receiving the stream, application decodes it with the system locale (&lt;em&gt;nls&lt;/em&gt; in user space).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;set-the-correct-value&quot;&gt;Set the correct value&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Suppose we have a VFAT fileystem initialized in Windows GBK sysetem. Now it will be mounted and used under Linux.&lt;/p&gt;

    &lt;p&gt;Shortname&apos;s codepage is cp936 while longname is Unicode.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Set &lt;em&gt;codepage=936&lt;/em&gt; mount option (without prefix &lt;em&gt;cp&lt;/em&gt;).
    &lt;ol&gt;
      &lt;li&gt;If you want to see the shortname, use &lt;em&gt;-t msdos&lt;/em&gt; instead of &lt;em&gt;-t vfat&lt;/em&gt;. Meanwhile, &lt;em&gt;iocharset&lt;/em&gt; is ignored.&lt;/li&gt;
      &lt;li&gt;Actually, we rarely use MSDOS nowadays. If you don&apos;t care, just leave it the default (in kernel).&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;iocharset=&lt;/em&gt; depends on system locale &lt;em&gt;xx_YY.ZZ&lt;/em&gt;:
    &lt;ol&gt;
      &lt;li&gt;If ZZ is Chinese encoding like GB2312, GBK, GB18030, then set &lt;em&gt;iocharset=cp936&lt;/em&gt; (with prefix &lt;em&gt;cp&lt;/em&gt;).&lt;/li&gt;
      &lt;li&gt;If ZZ is UTF-8, DO NOT set &lt;em&gt;iocharset=utf8&lt;/em&gt;! Instead, use &lt;em&gt;utf8&lt;/em&gt; alone while keeping the default &lt;em&gt;iocharset&lt;/em&gt; value.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If &lt;em&gt;iocharset=utf8&lt;/em&gt;, the kernel &lt;em&gt;vfat&lt;/em&gt; module allows lower case shortname which conflicts with Windows&apos;s tradition.&lt;/p&gt;

    &lt;p&gt;The kernel will throws a warning on such a case.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Remember the relevant NLS is compiled as Y or M.&lt;/li&gt;
  &lt;li&gt;The default &lt;em&gt;codepage&lt;/em&gt; and &lt;em&gt;iocharset&lt;/em&gt; (maybe &lt;em&gt;utf8&lt;/em&gt;) value can be set in kernel.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ntfs&quot;&gt;NTFS&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Shortname has nothing to do with NTFS. There is not such mount option as &lt;em&gt;codepage&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;iocharset&lt;/em&gt; option of NTFS has changed to &lt;em&gt;nls&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Similarly, if &lt;em&gt;nls=utf8&lt;/em&gt;, you can use &lt;em&gt;ntf8&lt;/em&gt; alone.&lt;/p&gt;

    &lt;p&gt;There does not exist lower/upper case filename issue with &lt;em&gt;nls=utf8&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>HTTPd</title>
   <link href="/2016/11/15/httpd/"/>
   <updated>2016-11-15T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/11/15/httpd</id>
   <content type="html">&lt;h1 id=&quot;lightweight-httpd&quot;&gt;Lightweight HTTPd&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Python&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/workspace/webui-aria2
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; http.server 6801 &amp;amp;
or
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python2 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; SimpleHTTPServer 6801 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Really primitive. Use it if you are lazy :).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://unix4lyfe.org/darkhttpd&quot;&gt;darkhttpd&lt;/a&gt;;&lt;/p&gt;

    &lt;p&gt;It&apos;s pretty handy for temporary serving a &lt;em&gt;static&lt;/em&gt; web page with multiple extended feature than Python&apos;s.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# darkhttpd /var/public_html --chroot --daemon --no-listing --uid nobody --gid nobody --maxconn 1 --log /var/public_html/traces.log&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;darkhttpd ~/opt/public_html &lt;span class=&quot;nt&quot;&gt;--daemon&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--no-listing&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--maxconn&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--log&lt;/span&gt; ~/opt/public_html/traces.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Default port under &lt;em&gt;root&lt;/em&gt; is 80 while 8080 for normal accounts. We can take vantage of &lt;em&gt;iptable&lt;/em&gt;&apos;s REDIRECT module of &lt;em&gt;nat&lt;/em&gt; table.&lt;/p&gt;

        &lt;p&gt;If &lt;em&gt;darkhttpd&lt;/em&gt; is running on &lt;em&gt;remote&lt;/em&gt; host (i.e. real deployment), use PREROUTING chain:&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;Loopback devices (like localhost) do not use the PREROUTING chain. If &lt;em&gt;darkhttpd&lt;/em&gt; is running on &lt;em&gt;localhost&lt;/em&gt; (i.e. for test), use OUTPUT chain:&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# iptables -t nat -I OUTPUT -d 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to-ports 8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;Hence, there is no need to specify 8080 port in web URL.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Only &lt;em&gt;root&lt;/em&gt; can and must &lt;em&gt;chroot&lt;/em&gt; and &lt;em&gt;drop privileges&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;lighttpd;
    &lt;ol&gt;
      &lt;li&gt;Suffer from &lt;em&gt;memory leak&lt;/em&gt;?&lt;/li&gt;
      &lt;li&gt;Support CGI/FastCGI.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;nginx;
    &lt;ol&gt;
      &lt;li&gt;Good at &lt;em&gt;static&lt;/em&gt; web page.&lt;/li&gt;
      &lt;li&gt;Popular than &lt;em&gt;lighttpd&lt;/em&gt;?&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;cname-vs-url-forward&quot;&gt;&lt;a href=&quot;https://www.namecheap.com/support/knowledgebase/article.aspx/9604/2237/types-of-domain-redirects--301-302-url-redirects-url-frame-and-cname&quot;&gt;CNAME vs URL Forward&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;A CNAME record is carried out on DNS server, irrelevant to server (SSH, HTTP, FTP etc.). That is to say, the CNAME url is not hosted on your servers at all.&lt;/p&gt;

    &lt;p&gt;The CNAME translation process is &lt;em&gt;transparent&lt;/em&gt; to browse client, without user end involvement.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;URL Forward is usually done on web server.&lt;/p&gt;

    &lt;p&gt;The server examines the &lt;em&gt;host&lt;/em&gt; field of HTTP header, and &lt;em&gt;return back the target URL&lt;/em&gt; to browser client if that matches a Redirect/Forward rule.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;URL Forward is divided into two categories:
    &lt;ol&gt;
      &lt;li&gt;By terminology, Forward and Redirect are used interchangeably, depending on the context. But usually, Forward is a broader concept, meaning Redirect or Frame.&lt;/li&gt;
      &lt;li&gt;URL Redirect (i.e. 301, 302 Unmasked) is what we usually refer to. The browser gets a HTTP 3XX status code and &lt;em&gt;moves permanently&lt;/em&gt; to the new site. Broswer address bar is updated to the target URL.&lt;/li&gt;
      &lt;li&gt;URL Frame (Cloaking/Masking) is similar but keep the original fetched web page. The new HTTP response will be &lt;em&gt;embedded&lt;/em&gt; as a &lt;em&gt;frame&lt;/em&gt; so that the visitor will always see the original URL in the address bar.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Platforms like Cloudclare, Freenom etc. support URL Forward nowadays.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/willurd/5720255&quot;&gt;Big list of http static server one-liners&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.alpinelinux.org/wiki/Darkhttpd&quot;&gt;alpinelinux wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Bootloader</title>
   <link href="/2016/10/27/bootloader/"/>
   <updated>2016-10-27T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/10/27/bootloader</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;UEFI (also named as EFI) firmware on system board is the primary bootloader.
    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Efibootmgr&quot;&gt;&lt;em&gt;sys-boot/efibootmgr&lt;/em&gt;&lt;/a&gt; application is not a bootloader; it is a tool to interact with the UEFI firmware and update its settings.&lt;/li&gt;
      &lt;li&gt;Enable &lt;em&gt;CONFIG_EFI_VARS&lt;/em&gt; so that the system firmware can be manipulated via &lt;em&gt;efibootmgr&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Grub/LILO etc. are secondary bootloaders with more flexible extensions.
    &lt;ol&gt;
      &lt;li&gt;Secondary bootloader is not a requirement, even for multiple boot entries.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;The kernel must have specific options enabled to be &lt;a href=&quot;https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Bootloader#Alternative_2:_efibootmgr&quot;&gt;directly&lt;/a&gt; bootable by the system&apos;s UEFI firmware (&lt;em&gt;CONFIG_EFI&lt;/em&gt; and &lt;em&gt;CONFIG_EFI_STUB&lt;/em&gt;).
    &lt;ol&gt;
      &lt;li&gt;Be sure to read though the &lt;a href=&quot;https://wiki.gentoo.org/wiki/EFI_stub_kernel&quot;&gt;EFI stub kernel&lt;/a&gt; article before continuing.&lt;/li&gt;
      &lt;li&gt;To reiterate, &lt;em&gt;efibootmgr&lt;/em&gt; is not a requirement to directly boot an UEFI system. The Linux kernel itself can be booted immediately.&lt;/li&gt;
      &lt;li&gt;Additional kernel command-line options can be built-in to the Linux kernel (&lt;em&gt;CONFIG_CMDLINE&lt;/em&gt;).&lt;/li&gt;
      &lt;li&gt;Even an &lt;em&gt;initramfs&lt;/em&gt; can be &apos;built-in&apos; to the kernel, which is not recommended. To support &lt;em&gt;initramfs&lt;/em&gt; directly, passing a parameter to the primary UEFI bootloader with the help of &lt;em&gt;efibootmgr&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;For additional kernels or Windows, enable &lt;em&gt;CONFIG_EFI_VARS&lt;/em&gt;. Then create another UEFI entries by &lt;em&gt;efibootmgr&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Keyboard layout</title>
   <link href="/2016/10/14/keyboard-layout/"/>
   <updated>2016-10-14T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/10/14/keyboard-layout</id>
   <content type="html">&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Emacs users are subject to &lt;a href=&quot;https://www.emacswiki.org/emacs/RepeatedStrainInjury&quot;&gt;Emacs pinky&lt;/a&gt;. Common solution is to  &lt;em&gt;switch Caps and Ctrl&lt;/em&gt; or &lt;em&gt;turn off Caps&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Caps is recommended to turned off as it&apos;s only used occasionally. What&apos;s more, we can use Shift to &lt;em&gt;shout&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Setting for virtual termnial is different from that of X, and should be set respectively.&lt;/li&gt;
  &lt;li&gt;In this post, I assume Intel PC and QWERTY keybord.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;virtual-terminal-openrc&quot;&gt;Virtual Terminal (OpenRC)&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;In Virtual Terminal, without specific clarification, term &lt;em&gt;layout&lt;/em&gt; refers to &lt;em&gt;keymap&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Keyboard layout can be found under &lt;em&gt;/usr/share/keymaps&lt;/em&gt;. Keymap compressed in &lt;em&gt;.gz&lt;/em&gt; format. Depending on the hardware, they are organized in sub-directories.&lt;/p&gt;

    &lt;p&gt;For Intel QWERTY keyboard, the default keymap is &lt;em&gt;i386/qwerty/us.map.gz&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Among other keymaps, there is a special &lt;em&gt;include&lt;/em&gt; directory offer supplemental keymap &lt;em&gt;extensions&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are two import parameters in &lt;em&gt;/etc/conf.d/keymaps&lt;/em&gt;, namely &lt;em&gt;keymap&lt;/em&gt; and &lt;em&gt;extended_keymaps&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;keymap=us&lt;/em&gt; sets keyboard layout to &lt;em&gt;us.map.gz&lt;/em&gt; while &lt;em&gt;extended_keymaps&lt;/em&gt; is a comma-listed &lt;em&gt;extension&lt;/em&gt;s.&lt;/p&gt;

    &lt;p&gt;In this post, we will ignore &lt;em&gt;extended_keymaps&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To switch Caps/Ctrl or turn off Caps, we can modiy the &lt;em&gt;keycode&lt;/em&gt; in keymap (decompressed). Before that, let&apos;s examine the &lt;em&gt;us.map&lt;/em&gt; format:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;include &quot;linux-with-alt-and-altgr&quot;
keycode  29 = Control
keycode  58 = Caps_Lock
keycode  97 = Control
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;include&lt;/em&gt; &lt;em&gt;extend&lt;/em&gt;s the current keymap.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;keycode 29 = Control&lt;/em&gt; means the Ctrl key is pressed which also applies to 58 and 97.&lt;/li&gt;
      &lt;li&gt;Specially 97 means the right Ctrl key while 29 is left Ctrl key.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Switch Caps and left Ctrl:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;keycode  29 = Caps_Lock
keycode  58 = Control
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Just swap the keycode for Control and Caps_Lock. Yeah, right, you can swap 29 and 97 (right Control) as well.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Turn off Caps:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;keycode  58 = Control
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Although modification the original default &lt;em&gt;us.map.gz&lt;/em&gt; is handy, create a new keymap is preferrable.&lt;/p&gt;

    &lt;p&gt;Create &lt;em&gt;caps-off.map&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;include &quot;us.map&quot;
keycode  58 = Control
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Remember to compress the new keymap:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;gzip &lt;/span&gt;caps-off.map
&lt;span class=&quot;c&quot;&gt;# mv caps-off.map.gz /usr/share/keymaps/i386/qwerty/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Then set &lt;em&gt;keymap=caps-off&lt;/em&gt; in &lt;em&gt;/etc/conf.d/keymaps&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Finally restart &lt;em&gt;keymaps&lt;/em&gt; service:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# rc-service keymaps restart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Interestingly, someone already compose a customized &lt;em&gt;/usr/share/keymaps/i386/qwerty/emacs.map.gz&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;I have chosen to use this one &lt;em&gt;keymap=emacs&lt;/em&gt;. It includes much more customization for Emacs.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Attention: changing &lt;em&gt;/etc/conf.d/keymaps&lt;/em&gt; directly affects only Virtual Terminal.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;x&quot;&gt;X&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Aside from changing &lt;em&gt;keymap&lt;/em&gt;s, X supports XKB in &lt;em&gt;/usr/share/X11/xkb/rules/base.lst&lt;/em&gt; instead of raw &lt;em&gt;keycode&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;X KeyBoard extension, or XKB, defines the way keyboards codes are handled in X, and provides access to internal translation tables. It is the basic mechanism that allows using multiple keyboard layouts in X.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(deprecated) &lt;em&gt;x11-apps/xmodmap&lt;/em&gt; is a somewhat low level tool, similar to OpenRC &lt;em&gt;/etc/conf.d/keymaps&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;xmodmap&lt;/em&gt; can temporarily change keymaps on command line (Terminal Emulator). However, for persistent effect,  create a configuration file &lt;em&gt;~/.Xmodmap&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;!
! Swap Caps_Lock and Control_L
!
remove Lock = Caps_Lock
remove Control = Control_L
keysym Control_L = Caps_Lock
keysym Caps_Lock = Control_L
add Lock = Caps_Lock
add Control = Control_L
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Insert &lt;em&gt;xmodmap ~/.Xmodmap&lt;/em&gt; command to &lt;em&gt;~/.xinitrc&lt;/em&gt;,  &lt;em&gt;~/.Xresources&lt;/em&gt;, &lt;em&gt;~/.xprofile&lt;/em&gt; (Gnome Display Manager) or whatever. Alternatively, we can add it to desktop&apos;s &lt;em&gt;autostart&lt;/em&gt; list. Most desktops (Xfce4, Gnome, or KDE) supports such setting.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;XKB command line tool &lt;em&gt;x11-apps/setxkbmap&lt;/em&gt; is a relativelly high level tool. If present, it resets &lt;em&gt;/etc/conf.d/keymap&lt;/em&gt; and &lt;em&gt;xmodmap&lt;/em&gt; settings.&lt;/p&gt;

    &lt;p&gt;Edit &lt;em&gt;~/.xinitrc&lt;/em&gt; or &lt;em&gt;~/.xprofile&lt;/em&gt; and call &lt;em&gt;setxkbmap&lt;/em&gt; from there.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/usr/bin/setxkbmap -option &quot;ctrl:swapcaps&quot;
or
/usr/bin/setxkbmap -option &quot;ctrl:nocaps&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;XKB in Xorg configuration&lt;/p&gt;

    &lt;p&gt;Without installing &lt;em&gt;setxkbmap&lt;/em&gt; package, we can use XKB rules in &lt;em&gt;/etc/X11/xorg.conf.d/10-keyboard.conf&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Section &quot;InputClass&quot;
    Identifier      &quot;keyboard-all&quot;
    MatchIsKeyboard &quot;on&quot;
    #Option  &quot;XkbOptions&quot;    &quot;ctrl:swapcaps&quot;
    #Option  &quot;XkbOptions&quot;    &quot;terminate:ctrl_alt_bksp&quot;
    Option  &quot;XkbOptions&quot;    &quot;ctrl:nocaps&quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Restart X to take effect.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Keyboard_layout_switching&quot;&gt;Keyboard layout switching&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.emacswiki.org/emacs/MovingTheCtrlKey&quot;&gt;Moving the Ctrl key&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Keyboard_configuration_in_Xorg&quot;&gt;keybord configuration in Xorg&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/X_KeyBoard_extension&quot;&gt;x keybord extension XKB&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>DISQUS on GitHub page</title>
   <link href="/2016/09/11/disqus/"/>
   <updated>2016-09-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/09/11/disqus</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;DISQUS is a centralized excel comments management tool. This post introduces basically how to add disqus plugin into a GitHub page generated by Jekyll.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;disqus&quot;&gt;DISQUS&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;First of all, you should go to &lt;a href=&quot;https://disqus.com&quot;&gt;disqus&lt;/a&gt; and signup.&lt;/li&gt;
  &lt;li&gt;Add your site to DISQUS. You can do this on the &lt;em&gt;admin&lt;/em&gt; panel. DISQUS might direct you there automatically.&lt;/li&gt;
  &lt;li&gt;You should fill in some basic information like &lt;em&gt;disqus shortname&lt;/em&gt; to identify your GitHub site, GitHub site url etc. In the &lt;em&gt;community&lt;/em&gt; setting, Comments Count Link, change &lt;em&gt;0 Comments&lt;/em&gt; to &lt;em&gt;Leave Comments&lt;/em&gt;. In the &lt;em&gt;advanced&lt;/em&gt; setting part, you&apos;d best fill in the &lt;em&gt;trusted domain&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Finally you will get a piece of code depends on site platform. Since there is no default Jekyll platform, you choose &lt;em&gt;universal code&lt;/em&gt; almost like this:&lt;/p&gt;

    &lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;disqus_thread&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
 *  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
 *  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables
 */&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;disqus_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;{{ page.url | prepend: site.url }}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Replace PAGE_URL with your page&apos;s canonical URL variable&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;identifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;{{ page.id }}&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Replace PAGE_IDENTIFIER with your page&apos;s unique identifier variable&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// REQUIRED CONFIGURATION VARIABLE: EDIT THE SHORTNAME BELOW&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;//EXAMPLE.disqus.com/embed.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// IMPORTANT: Replace EXAMPLE with your forum shortname!&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;data-timestamp&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;noscript&amp;gt;&lt;/span&gt;Please enable JavaScript to view the &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://disqus.com/?ref_noscript&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nofollow&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;comments powered by Disqus.&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/noscript&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dsq-count-scr&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;//EXAMPLE.disqus.com/count.js&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;async&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Pay attention to:
    &lt;ol&gt;
      &lt;li&gt;Edit and uncomment the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disqus_config&lt;/code&gt; part. Replace PAGE_URL and PAGE_IDENTIFIER with your own Jekyll page variable.&lt;/li&gt;
      &lt;li&gt;Replace the EXAMPLE part with the &lt;em&gt;disqus shortname&lt;/em&gt; just created for your GitHub site. That&apos;s all!&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;embedding&quot;&gt;Embedding&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;After updating the code snippet, you will embed the code into your GitHub site source code.&lt;/li&gt;
  &lt;li&gt;Insert the code snippet between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{% if layout.comments %}&lt;/code&gt; and &lt;code&gt;&amp;#123;% endif %}&lt;/code&gt; of newly created &lt;em&gt;_includes/disqus.html&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Insert &lt;code&gt;&amp;#123;% include disqus.html %}&lt;/code&gt; into &lt;em&gt;_layouts/default.html&lt;/em&gt; after the &lt;code&gt;&amp;#123;{ content }}&lt;/code&gt; part. The consequent code is like:&lt;/p&gt;

    &lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
     
  {{ content }}
  {% include disqus.html %}
     
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Insert a YAML Front Matter &lt;em&gt;comments: true&lt;/em&gt; line into &lt;em&gt;_layouts/page.html&lt;/em&gt; and &lt;em&gt;_layouts/post.html&lt;/em&gt; respectively.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&amp;#123;% if layout.comments %}&lt;/code&gt; could be &lt;code&gt;&amp;#123;% if page.comments %}&lt;/code&gt; depending on your needs. The latter requires &lt;em&gt;comments: true&lt;/em&gt; on each post YAML Front Matter to turn on DISQUS comments. But the former seems not able to disable comments for a specific post. Details refer to &lt;a href=&quot;https://jekyllrb.com/docs/variables/&quot;&gt;Jekyll variable&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Up to now, you would have create a new file &lt;em&gt;disqus.html&lt;/em&gt;, updated &lt;em&gt;default.html&lt;/em&gt;, &lt;em&gt;page.html&lt;/em&gt; and &lt;em&gt;post.html&lt;/em&gt;. That&apos;s all!&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;comments-counter&quot;&gt;Comments Counter&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Besides comments, you can display the number of comments on a post.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Insert:&lt;/p&gt;

    &lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dsq-count-scr&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;//EXAMPLE.disqus.com/count.js&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;async&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;to the end of &lt;em&gt;_includes/disqus.html&lt;/em&gt; but before the last line &lt;code&gt;&amp;#123;% endif %}&lt;/code&gt;. The EXAMPLE should be replaced your real &lt;em&gt;disqus shortname&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Next insert:&lt;/p&gt;

    &lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   
{% if layout.comments %} • &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ site.url }}{{ page.url }}#disqus_thread&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Leave Comments&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;{% endif %}
   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;where you would like to show the comments counter. Usually, it should be &lt;em&gt;_layouts/post.html&lt;/em&gt;. You can also insert it into &lt;em&gt;index.html&lt;/em&gt; to show counters for each post on the front page of your site.&lt;/p&gt;

    &lt;p&gt;The key is the trailing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#disqus_thread&lt;/code&gt; which is the DIV id of the very first snippet code above. The &lt;em&gt;layout&lt;/em&gt; in &lt;code&gt;&amp;#123;% if layout.comments %}&lt;/code&gt; might be changed based on your previous choice.&lt;/p&gt;

    &lt;p&gt;That&apos;s all!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;censorship&quot;&gt;Censorship&lt;/h1&gt;

&lt;p&gt;Seemingly DISQUS does not show up due to GFW block. To get this solved, you must:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Enable HTTPS for your site url. If you did not set a customized domain, then good luck. The original default GitHub page is accessed by HTTPS. Otherwise, you must set your own HTTPS which usually needs payment service.&lt;/li&gt;
  &lt;li&gt;Use a proxy to visit your HTTPS site.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://sgeos.github.io/jekyll/disqus/2016/02/14/adding-disqus-to-a-jekyll-blog.html&quot;&gt;sgeso main&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.perfectlyrandom.org/2014/06/29/adding-disqus-to-your-jekyll-powered-github-pages/&quot;&gt;perfectlyrandom&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://desiredpersona.com/disqus-comments-jekyll/&quot;&gt;desiredperson&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Intel Graphics</title>
   <link href="/2016/09/10/intel-graphics/"/>
   <updated>2016-09-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/09/10/intel-graphics</id>
   <content type="html">&lt;p&gt;It&apos;s long-lasting panic to handle Intel HD3000 graphics corruption, tearing, judder, glitch etc. Desktop GUI get stuck without any responding. MPV playback spreads dots all over. Worsely, switches between virtual terminal and X freeze the desktop applications.&lt;/p&gt;

&lt;h1 id=&quot;intel-ddx&quot;&gt;Intel DDX&lt;/h1&gt;

&lt;p&gt;It is almost deprecated but has better performance. We should manually install the official relevant Intel driver:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# emerge -avt x11-drivers/xf86-video-intel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then configure Xorg to adopt it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/X11/xorg.conf.d/20-intel.conf

Section &quot;Device&quot;
        Identifier        &quot;Intel Graphics&quot;
        Driver        &quot;intel&quot;
#       Option        &quot;AccelMethod&quot;        &quot;uxa&quot;
        Option        &quot;AccelMethod&quot;        &quot;sna&quot;
#       Option        &quot;TearFree&quot;        &quot;true&quot;
        Option        &quot;DRI&quot;        &quot;2&quot;
#       Option        &quot;DRI&quot;        &quot;3&quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This driver is just maintained but no new features or bug fixes available.&lt;/p&gt;

&lt;h1 id=&quot;modesetting-ddx&quot;&gt;Modesetting DDX&lt;/h1&gt;

&lt;p&gt;This is now the default driver on newer Intel graphics chipsets for Gentoo. It is more generic and actively developed. As of &lt;em&gt;x11-base/xorg-drivers-1.19&lt;/em&gt;, this has become the default for Gentoo.&lt;/p&gt;

&lt;p&gt;Firstly, enable global &lt;em&gt;glamor&lt;/em&gt; USE:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/portage/make.conf

USE=&quot;glamor&quot;
VIDEO_CARDS=&quot;intel i965&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, Xorg configuration:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/X11/xorg.conf.d/20-modesetting.conf

Section &quot;Device&quot;
    Identifier  &quot;Intel Graphics&quot;
    Driver      &quot;modesetting&quot;
    Option      &quot;AccelMethod&quot;    &quot;glamor&quot;
    Option      &quot;DRI&quot;            &quot;3&quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note, if both &lt;em&gt;20-intel.conf&lt;/em&gt; and &lt;em&gt;20-modesetting.conf&lt;/em&gt; are defined in &lt;em&gt;/etc/X11/xorg.conf.d/&lt;/em&gt;, the X server will attempt to load the files in alpha-numeric order.&lt;/p&gt;

&lt;h1 id=&quot;xorg-arguments&quot;&gt;Xorg arguments&lt;/h1&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;startx &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; vt7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Arguments after the two dashes are passed to Xorg server. Default OpenRC Xinit configuration is located under &lt;em&gt;/etc/X11/xinit&lt;/em&gt;. However it fails to set the correct virtual terminal (i.e. vt7) to start X, resulting in X freezes upon switches between X and virtual terminal.&lt;/p&gt;

&lt;p&gt;Alternatively, &lt;em&gt;vt7&lt;/em&gt; can be passed to X server directly in &lt;em&gt;~/.xserverrc&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; /usr/bin/X &lt;span class=&quot;nt&quot;&gt;-nolisten&lt;/span&gt; tcp &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; vt7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;thinkpad-buttons&quot;&gt;ThinkPad Buttons&lt;/h1&gt;

&lt;p&gt;https://wiki.gentoo.org/wiki/ACPI/ThinkPad-special-buttons&lt;/p&gt;

&lt;h1 id=&quot;screen-brightness&quot;&gt;Screen brightness&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/default/grub

acpi_osi=&quot;!Windows 2012&quot;
# -or-
acpi_osi=&quot;Linux&quot;

acpi_backlight=&quot;video&quot;
# -or-
acpi_backlight=&quot;vendor&quot;
# -or-
acpi_backlight=&quot;native&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At the time of writing this post, correct combination is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acpi_osi=&quot;!Windows 2012&quot; acpi_backlight=&quot;video&quot;&lt;/code&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Disk Partitioning and Filesystem</title>
   <link href="/2016/05/27/disk-partitioning/"/>
   <updated>2016-05-27T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/05/27/disk-partitioning</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#hard-disk-drive-hdd&quot; id=&quot;markdown-toc-hard-disk-drive-hdd&quot;&gt;Hard Disk Drive (HDD)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#firmware-and-interface&quot; id=&quot;markdown-toc-firmware-and-interface&quot;&gt;Firmware and Interface&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#partitioning-table&quot; id=&quot;markdown-toc-partitioning-table&quot;&gt;Partitioning table&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#booting-scheme&quot; id=&quot;markdown-toc-booting-scheme&quot;&gt;Booting scheme&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#partitioning-tool&quot; id=&quot;markdown-toc-partitioning-tool&quot;&gt;Partitioning tool&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sector&quot; id=&quot;markdown-toc-sector&quot;&gt;Sector&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#minimal-alignment&quot; id=&quot;markdown-toc-minimal-alignment&quot;&gt;Minimal Alignment&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#optimal-alignment&quot; id=&quot;markdown-toc-optimal-alignment&quot;&gt;Optimal Alignment&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#alignment-summary&quot; id=&quot;markdown-toc-alignment-summary&quot;&gt;Alignment Summary&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#filesystem&quot; id=&quot;markdown-toc-filesystem&quot;&gt;Filesystem&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#bootable-usb-stick&quot; id=&quot;markdown-toc-bootable-usb-stick&quot;&gt;Bootable USB stick&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#operating-system-limitations&quot; id=&quot;markdown-toc-operating-system-limitations&quot;&gt;Operating System Limitations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#summary&quot; id=&quot;markdown-toc-summary&quot;&gt;Summary&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#manually-creating-windows-uefi-bootable-usb-stick&quot; id=&quot;markdown-toc-manually-creating-windows-uefi-bootable-usb-stick&quot;&gt;Manually creating Windows UEFI bootable USB stick&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#windows-7-notes&quot; id=&quot;markdown-toc-windows-7-notes&quot;&gt;Windows 7 Notes&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;hard-disk-drive-hdd&quot;&gt;Hard Disk Drive (HDD)&lt;/h1&gt;

&lt;p&gt;In terms of transmission method:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Parallel: IDE/ATA/PATA; SCSI.&lt;/li&gt;
  &lt;li&gt;Serial: Serial ATA/SATA; Serial Attached SCSI/SAS.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In terms of application:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;SCSI/SAS: workstation, RAID.&lt;/li&gt;
  &lt;li&gt;ATA/SATA: PC.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In terms of features:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;ATA/SATA: hotplug; cheap; warm-friendly.&lt;/li&gt;
  &lt;li&gt;SCSI/SAS: stable; higher performance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;firmware-and-interface&quot;&gt;Firmware and Interface&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Firmware refers to underlying hardware as &apos;UEFI Firmware&apos; or &apos;BIOS Firmware&apos;. Nowadays, almost all PCs bring in UEFI Firmware.&lt;/li&gt;
  &lt;li&gt;At the very beginning of booting, we press ESC/F2/F12 and get into &apos;Firmware interface&apos; as System BIOS, ROM BIOS or PC BIOS which is also named to BIOS Setting.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;partitioning-table&quot;&gt;Partitioning table&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;GPT&lt;/li&gt;
  &lt;li&gt;MBR (MSDOS)&lt;/li&gt;
  &lt;li&gt;MAC&lt;/li&gt;
  &lt;li&gt;BSD&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;booting-scheme&quot;&gt;Booting scheme&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Legacy (BIOS) booting&lt;/li&gt;
  &lt;li&gt;UEFI booting.&lt;/li&gt;
  &lt;li&gt;UEFI Firmware supports either UEFI booting or Legacy booting, which is called Compatibility Support Module (CSM).&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;partitioning-tool&quot;&gt;Partitioning tool&lt;/h1&gt;

&lt;p&gt;To create partition table and partitions&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;parted&lt;/li&gt;
  &lt;li&gt;fdisk&lt;/li&gt;
  &lt;li&gt;diskpart on Windows&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both &lt;em&gt;fdisk&lt;/em&gt; and &lt;em&gt;parted&lt;/em&gt; are partitioning utilities. &lt;em&gt;fdisk&lt;/em&gt; is well known, stable, and recommended for the MBR partition layout while &lt;em&gt;parted&lt;/em&gt; was one of the first Linux block device management utilities to support GPT partitions.&lt;/p&gt;

&lt;h1 id=&quot;sector&quot;&gt;&lt;a href=&quot;https://www.ibm.com/developerworks/cn/linux/l-linux-on-4kb-sector-disks/index.html&quot;&gt;Sector&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;Read &lt;a href=&quot;http://fibrevillage.com/storage/563-storage-i-o-alignment-and-size&quot;&gt;Storage I/O Alignment and Size&lt;/a&gt; first! It is imperative to differentiate the concepts of &lt;em&gt;physical sector&lt;/em&gt; and &lt;em&gt;logical sector&lt;/em&gt;, especially on partitions alignment.&lt;/p&gt;

&lt;p&gt;On the hardware level, we have sectors with 512B (0.5KiB) in the old days. In order to improve disk scability and abilities of error check, new disk drives with 4096B (4KiB) sectors are inovated. It is nonnegligible that there exist gaps between physical sectors, data within which could be utilized to detect disk error and recovery partial data.&lt;/p&gt;

&lt;p&gt;For backward compatibility, we have physical sector and logical sector, which is called &lt;em&gt;advanced format feature&lt;/em&gt;. Many ancient operating systems does not support reading sectors with 4KiB. Consequently, operating systems still read and write logical sectors of 512B (0.5KiB) while disk driver operates on physical sectors in 4096B (4KiB). Here is an example output of &lt;em&gt;parted&lt;/em&gt; command. It makes sense that partition size is presented with logical sectors, when &lt;em&gt;unit&lt;/em&gt; is selected to _s_ector.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Model: ATA HITACHI HTS72323 (scsi)
Disk /dev/sda: 625142448s
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags: 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Obviously, 1 physical sector corresponds to 8 logical sectors. We can check both values through Linux runtime &lt;a href=&quot;http://fibrevillage.com/storage/563-storage-i-o-alignment-and-size&quot;&gt;sysfs&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/sys/block/sdX/queue/physical_block_size
/sys/block/sdX/queue/logical_block_size

/sys/block/sdX/alignment_offset          # 0
/sys/block/sdX/sdXY/alignment_offset     # 0

/sys/block/sdX/queue/optimal_io_size     # 1048576 = 1024 * 1024 = 1MiB
/sys/block/sdX/queue/minimum_io_size
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;fdisk&lt;/em&gt; can also reports &lt;em&gt;optimal_io_size&lt;/em&gt; and &lt;em&gt;minimum_io_size&lt;/em&gt;. To get authorative results, we resort to the disk official page by checking disk model first:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/sys/block/sdX/device/model
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For the purpose of disk performance, please align the logical partition table addresses to actual physical blocks on the disks. Make sure partitions &lt;strong&gt;start&lt;/strong&gt; at boundaries of:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(optimal_io_size + alignment_offset) / physical_block_size = 256 physical sectors
# -or-
(minimal_io_size + alignment_offset) / physical_block_size
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alignment does not care about the ending boundary at all. That is to say, space gap may exist between partitions.&lt;/p&gt;

&lt;h2 id=&quot;minimal-alignment&quot;&gt;Minimal Alignment&lt;/h2&gt;

&lt;p&gt;Keep in mind, on software layer (both OSes and partitioning tools), &lt;em&gt;s&lt;/em&gt;ector is equivalent to logical sector. We sometimes call partition boundaries on software level as &lt;em&gt;logical sector address&lt;/em&gt; (LBA).&lt;/p&gt;

&lt;p&gt;We are suggested to create partitions at the exact boundary of physical blocks, namely oders of 4096 (8s) like 40s, 48s, etc.&lt;/p&gt;

&lt;p&gt;For instance. I want to create a &lt;a href=&quot;https://wiki.archlinux.org/index.php/Grub#GUID_Partition_Table_(GPT)_specific_instructions&quot;&gt;Grub GPT/BIOS boot partition&lt;/a&gt;. Although alignment is not critical to this partition (not regularly accessed), I present it here to illustrate the rules above.&lt;/p&gt;

&lt;p&gt;Usually, a Grub BIOS boot partition takes around 1MiB = 2048s. On GPT disks, the very &lt;a href=&quot;https://askubuntu.com/q/199413&quot;&gt;first usable sector is 34s&lt;/a&gt; since the size of the EFI label is usually 34 sectors (0s - 33s).&lt;/p&gt;

&lt;p&gt;So we can choose the starting sector to be 40s and the ending point be 2047s (included). Please be noted, here we use 2047s as the ending sector such that the next partition can start at 2048s. Hence, a properly aligned partition ends at &lt;em&gt;multiple 8s minus 1&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / # parted -a opt /dev/sda
(parted) unit s
(prated) mkpart primary 40s 2047s
Warning: The resulting partition is not properly aligned for best performance.
Ignore/Cancel?
(parted) Ignore
(parted) align-check opt 1
(parted) align-check min 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now that the the starting point and ending point is set appropriately, why does &lt;em&gt;parted&lt;/em&gt; still reports warning? Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-a opt&lt;/code&gt; tells the partition to align optimally. &lt;em&gt;minimal&lt;/em&gt; tells to align &lt;em&gt;precisely&lt;/em&gt; at multiple physical sectors. Please set &lt;em&gt;unit&lt;/em&gt; to KiB, MiB, or GiB (power of 2, orders of 1024): require &lt;strong&gt;exact&lt;/strong&gt; unit.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Use minimum alignment as given by the disk topology information. This and the opt value will use layout information provided by the disk to align the logical partition table  addresses to actual physical blocks on the disks. The min value is the minimum alignment needed to align the partition properly to physical blocks, which avoids performance degradation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;optimal-alignment&quot;&gt;Optimal Alignment&lt;/h2&gt;

&lt;p&gt;By default, &lt;em&gt;parted&lt;/em&gt; uses &lt;em&gt;optimal&lt;/em&gt; alignment at &lt;strong&gt;inexact&lt;/strong&gt; megabytes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Use optimum alignment as given by the disk topology information. This aligns to a multiple of the physical block size in a way that guarantees optimal performance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;em&gt;optimal&lt;/em&gt; uses inexact units like K, M or G (power of 10, oders of 1000). It aligns at a more general level, usually in MB and allows +/-500KB (500MB for GB unit) adjustment automatically, like &lt;em&gt;mkpart primary fat32 1MB 201MB&lt;/em&gt;.  Specially, we can set &lt;em&gt;unit %&lt;/em&gt;. Hence start a partition by &lt;em&gt;percentile&lt;/em&gt; is appreciated like &lt;em&gt;mkpart primary fat32 0% 551MB&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The resulting boundary is determined by &lt;strong&gt;optimal_io_size&lt;/strong&gt; (check the formula above). If the that value is zero, then conform to 1MiB. Therefore, in real practice, just use the exact units or percentiles, as alignment is guranteed.&lt;/p&gt;

&lt;h2 id=&quot;alignment-summary&quot;&gt;Alignment Summary&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;LVM partitions comply with with the same alignment rules above.&lt;/li&gt;
  &lt;li&gt;Interestingly, HD manufactures use order of 1000 to present disk size as that would make the number larger.&lt;/li&gt;
  &lt;li&gt;In math, 1MB is actually 1M Bytes while 1GiB is 1Gi Bytes.&lt;/li&gt;
  &lt;li&gt;We use unit _s_ector to create small partitions while MiB/GiB for large partitions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href=&quot;https://www.ibm.com/developerworks/cn/linux/l-linux-on-4kb-sector-disks/index.html&quot;&gt;4 KB 扇区磁盘上的 Linux：实用性建议&lt;/a&gt;; &lt;a href=&quot;https://superuser.com/questions/982680/whats-the-point-of-hard-drives-reporting-their-physical-sector-size&quot;&gt;What&apos;s the point of hard drives reporting their physical sector size?&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;filesystem&quot;&gt;Filesystem&lt;/h1&gt;

&lt;p&gt;&apos;Format&apos; refers to &lt;em&gt;create&lt;/em&gt; filesystem on a disk parition.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;NTFS&lt;/li&gt;
  &lt;li&gt;FAT 12/16/vfat/32&lt;/li&gt;
  &lt;li&gt;EXT 2/3/4, XFS&lt;/li&gt;
  &lt;li&gt;BTRFS&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;EFI System Partition (ESP) (including bootable USB stick) must be a FAT (FAT32 is recommended) filesystem. Now most Linux distributions use &lt;em&gt;xfs&lt;/em&gt; instead of &lt;em&gt;ext4&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;bootable-usb-stick&quot;&gt;Bootable USB stick&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;dd&lt;/em&gt; (rude but robust)&lt;/p&gt;

    &lt;p&gt;The ISO is installed to the whole USB stick as if it were a hard drive. This make USB stick unacessible to OS file manager due to &lt;em&gt;boot&lt;/em&gt; and/or &lt;em&gt;esp&lt;/em&gt; flag.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Rufus (reliable and versatile tool)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;diskpart&lt;/em&gt; (Windows)&lt;/li&gt;
  &lt;li&gt;Ubuntu Disk Creater&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Manual copy.&lt;/p&gt;

    &lt;p&gt;For UEFI booting, just copy (i.e. &lt;em&gt;rsync&lt;/em&gt;) ISO contents to a FAT32 USB partition without altering other partitions that can be used as data storage.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For Windows bootable USB stick, sometimes we encounter lack of the exact USB driver from the ISO, resulting in installation failure in the early phase. You are recommended to change the USB stick (i.e. a newer with USB 3.0 port). Optionally, you can get a driver copy and place it a location that is accessible during installation (i.e. within another USB stick).&lt;/p&gt;

&lt;h1 id=&quot;operating-system-limitations&quot;&gt;Operating System Limitations&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Usually, MBR and BIOS (MBR + BIOS), and GPT and UEFI (GPT + UEFI) go hand in hand without any compatibility issue. However, that matching is a must for Windows and Mac while Linux is more flexible.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For &lt;a href=&quot;https://wiki.archlinux.org/index.php/Windows_and_Arch_dual_boot&quot;&gt;Dual boot with Windows&lt;/a&gt;, turn off Windows &apos;Fast Reboot&apos; and &apos;Secure boot&apos; in BIOS setting.&lt;/p&gt;

    &lt;p&gt;What&apos;s more, then stick to the matching rule unless they are installed separately on two disks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;UEFI requires the firmware and operating system loader (or kernel) to be size-matched; for example, a 64-bit UEFI firmware implementation can load only a 64-bit operating system (OS) boot loader or kernel.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;summary&quot;&gt;Summary&lt;/h1&gt;

&lt;p&gt;The final booting scheme depends on:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Firmware: UEFI/BIOS Firmware;&lt;/li&gt;
  &lt;li&gt;BIOS setting: uefi/Legacy/CSM booting;&lt;/li&gt;
  &lt;li&gt;Partitioning: GPT/MBR;&lt;/li&gt;
  &lt;li&gt;Operating System (and boot loader thereof).&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;manually-creating-windows-uefi-bootable-usb-stick&quot;&gt;Manually creating Windows UEFI bootable USB stick&lt;/h1&gt;

&lt;p&gt;This tutorial shows how to manually create a Windows 8.1 bootable USB stick under Linux. &lt;strong&gt;parted does NOT ask for confirmation on each command like fdisk&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;On Windows, we use &lt;em&gt;diskpart&lt;/em&gt;. Alternatively, format the USB to FAT32 and copy all ISO files to the USB - quite simple!&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Create partition table - GPT&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# parted -a optimal /dev/sdb&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mktable/mklabel gpt
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; unit s
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; print free
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;mktable/mklabel&lt;/em&gt; &lt;strong&gt;ERASE&lt;/strong&gt;s the whole disk data!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create a &lt;em&gt;primary&lt;/em&gt; partition&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(parted) mkpart primary fat32 0% 5GiB
(parted) print free
(parted) align-check opt 1
(parted) name 1 Win81USB
(parted) print free
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;The &lt;em&gt;fat32&lt;/em&gt; argument is optional at this step. It may be specified to set an appropriate partition ID. &lt;em&gt;parted&lt;/em&gt; does not format filesystem.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;0%&lt;/em&gt; is better for &lt;em&gt;start&lt;/em&gt; of the very first partition alignment. Similarly, &lt;em&gt;100%&lt;/em&gt; is better for &lt;em&gt;end&lt;/em&gt; of the very last partition alignment.&lt;/li&gt;
      &lt;li&gt;5 GiB is enough for Windows 8.1 ISO. The remaining space can be used to store data (i.e. create &lt;em&gt;ext4&lt;/em&gt; partition).&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;align-check&lt;/em&gt; checks partition alignment. &lt;em&gt;optimal/opt&lt;/em&gt; guarantees optimal disk performance. Try to use &lt;em&gt;unit s&lt;/em&gt; (sector) when &lt;em&gt;mkpart&lt;/em&gt; for better disk performance.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(opt) Set the partition be &lt;em&gt;bootable&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;parted&lt;/em&gt; presents GPT partition GUIDs as &lt;em&gt;flags&lt;/em&gt; while other tools like &lt;em&gt;gdisk&lt;/em&gt; uses short codes (i.e. &lt;em&gt;ef00&lt;/em&gt;). However, those codes mean nothing at all in &lt;em&gt;parted&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(parted) set 1 boot on
or
(parted) toggle 1 esp
(parted) print free
(parted) quit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Enable either &lt;em&gt;boot&lt;/em&gt; or &lt;em&gt;esp&lt;/em&gt; as they imply each other (alias) on GPT disks. We can also set &lt;em&gt;msftdata&lt;/em&gt; for Windows stick.&lt;/li&gt;
      &lt;li&gt;As mentioned earlier, &lt;em&gt;boot&lt;/em&gt; or &lt;em&gt;esp&lt;/em&gt; flag makes this partition unacessible to Windows OS file manager.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Format FAT32 filesystem&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkfs.vfat -F32 /dev/sdb1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Though we sepcify &lt;em&gt;fat32&lt;/em&gt; argument in &lt;em&gt;parted&lt;/em&gt;, we must &lt;em&gt;explicitly&lt;/em&gt; format the partition.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mount ISO file&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mount -t udf -o loop,ro,unhide /path/to/file.iso /mnt/iso&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Make usre &lt;em&gt;udf_fs&lt;/em&gt; is enabled in kernel to support DVD ISO. The default &lt;em&gt;iso9660&lt;/em&gt; only supports CD ISO.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mount the USB stick&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mount /dev/sdb1 /mnt/usbstick&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Copy ISO files to USB stick&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cp -rv /mnt/iso/* /mnt/usbstick/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rsync -rv /mnt/iso/ /mnt/usbstick/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Flush file system buffers&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# sync&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Umount ISO and USB stick&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# umount /mnt/iso&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# umount /mnt/usbstick&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;For Windows 10 onwards, the &quot;install.wim&quot; file is over 4GB and cannot be copied to a FAT32 filesystem. So we need to &lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/split-a-windows-image--wim--file-to-span-across-multiple-dvds&quot;&gt;split the file&lt;/a&gt; into smaller ones before copying.&lt;/li&gt;
  &lt;li&gt;Refs
    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;https://superuser.com/questions/729087/fedora-create-windows-8-1-bootable-usb&quot;&gt;fedora create windows 8.1 USB stick&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://www.howtogeek.com/168137/mount-an-iso-image-in-linux/?PageSpeed=noscript&quot;&gt;howtogeek cd/dvd ISO mount&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;windows-7-notes&quot;&gt;Windows 7 Notes&lt;/h2&gt;

&lt;p&gt;By default, Windows 7 ISO does not prepare the &lt;em&gt;bootx64.exe&lt;/em&gt; and relevant directories correctly. Use robust tool like Rufus.&lt;/p&gt;

&lt;p&gt;For whatever reason you want to create usb stick by copying or &lt;em&gt;dd&lt;/em&gt;, please get &lt;em&gt;bootx64.exe&lt;/em&gt; from an existing Windows 7 OS. Alternatively, extract (i.e. by &lt;em&gt;7zip&lt;/em&gt;) &lt;em&gt;\1\Windows\Boot\EFI\bootmgfw.efi&lt;/em&gt; from ISO &lt;em&gt;\sources\install.wim&lt;/em&gt; and rename it to &lt;em&gt;bootx64.exe&lt;/em&gt;. From within the USB stick, copy &lt;em&gt;\efi\microsoft\boot&lt;/em&gt; directory to a upper level, namely &lt;em&gt;\efi\boot&lt;/em&gt; into which we put &lt;em&gt;bootx64.exe&lt;/em&gt;. Actually, Rufus just creates &lt;em&gt;\efi\boot&lt;/em&gt; directly instead of copying.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>aria2 + webui</title>
   <link href="/2016/05/24/aria2/"/>
   <updated>2016-05-24T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/05/24/aria2</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;aria2&lt;/em&gt; is a Linux command line counterpart of Windows Thunder/IDM, which supports URL, BT/PT, metalink etc. Make it simple, configure a GUI like Webui-aria2 or YAAW based on its builtin RPC (JSON or XML) support.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;installation-on-pc&quot;&gt;Installation on PC&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;net-misc/aria2 bittorrent metalink xmlrpc&quot; &amp;gt; /etc/portage/package.use/aria2&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt aria2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;If you prefer XML RPC to default JSON RPC, enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xmlrpc scripts&lt;/code&gt; USEs.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We can invoke &lt;em&gt;aria2&lt;/em&gt; command - &lt;em&gt;aria2c&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Refer to &lt;a href=&quot;https://aria2.github.io/manual/en/html/aria2c.html#example&quot;&gt;official examples&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;To fully utilize functionalities, we can:
    &lt;ol&gt;
      &lt;li&gt;Enable RPC and daemon;&lt;/li&gt;
      &lt;li&gt;Put common arguments in configuration file;&lt;/li&gt;
      &lt;li&gt;Install &lt;em&gt;webui-aria2&lt;/em&gt; and enable &lt;em&gt;directurl&lt;/em&gt;;&lt;/li&gt;
      &lt;li&gt;Set alias for different configurations.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation-on-openwrt&quot;&gt;Installation on OpenWRT&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;TO-DO&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;If you don&apos;t bother remembering arguments like me, speicify the common ones in &lt;em&gt;$HOME/.aria2/aria2.conf&lt;/em&gt; or &lt;em&gt;$XDG_CONFIG_HOME/aria2/aria2.conf&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;You can also specify a different configuration on command line by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--conf-path&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Current version is 1.15.2 and limited:
    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;${HOME}&lt;/em&gt; or &lt;em&gt;~&lt;/em&gt; cannot be parsed in configuration file. Use absolute path.&lt;/li&gt;
      &lt;li&gt;Doesn&apos;t support default &lt;em&gt;$XDG_CONFIG_HOME/aria2/aria2.conf&lt;/em&gt; location. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--conf-path&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;More options are only available in newer versions:&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# https://1024coder.com/topic/15
# https://gist.github.com/aa65535/5e956c4eb4f451ddec29
# http://aria2c.com/usage.html
# http://blog.binux.me/2012/12/aria2-examples/
#
# Version 1.15.2 does not support ${HOME} or ~ in .conf

# Log
#
log=/home/jim/.local/share/aria2/aria2.log
log-level=debug
summary-interval=120

# Disk
#
dir=/home/jim/Downloads
# Allocates file space before download begins
# This may take some time depending on file size
# and filesystem
# NTFS: falloc; Ext3/4: trunc
# Refer to `dir&apos; option
file-allocation=none
#enable-mmap=true
# &amp;gt;= 1.16
#disk-cache=32M

# Concurrency
#
# Resume a download started by a web browser or another program
# which downloads files sequentially from the beginning
continue=true
# maximum downloads
max-concurrent-downloads=3
# maximum connections to one server per download
max-connection-per-server=3
# connections/threads per download 
split=5
# split if file &amp;gt;= 2*5M=10M
min-split-size=5M
# overall limit
max-overall-upload-limit=1K
max-overall-upload-limit=0
# Avoid terribly slow AAAA record lookup
disable-ipv6=true

# Session
#
input-file=/home/jim/.local/share/aria2/aria2.session
save-session=/home/jim/.local/share/aria2/aria2.session
# &amp;gt;= 1.16.1
#save-session-interval=60

# RPC
#
daemon=true
enable-rpc=true
rpc-allow-origin-all=true
# If used in OpenWRT, use &apos;true&apos;
#rpc-listen-all=false
# Customize port number if the default is occupied
#rpc-listen-port=6800
rpc-user=aria2
rpc-passwd=aria2c
# better but &amp;gt;= 1.18.4
#rpc-secret=token

# BT/PT
#
#follow-torrent=true
#bt-max-peers=55
#listen-port=6881-6999
#dht-listen-port=6881-6999
#bt-request-peer-speed-limit=50K

# schedulled command; useful in OpenWRT
#on-download-complete=exit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;pt-camouflage&quot;&gt;PT camouflage&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;PT sites (mainly those on campus) forbid &lt;em&gt;aria2&lt;/em&gt;. We should disguise it behaving like a normal &lt;em&gt;uTorrent&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# PT camouflage
#
# https://www.librehat.com/aria2-camouflage-utorrent-pt-download/
# http://tieba.baidu.com/p/2894158631
# http://kzpu.com/archives/3526.html
enable-dht=false
enable-dht6=false
bt-enable-lpd=false
enable-peer-exchange=false
user-agent=uTorrent/341(109279400)(30888)
peer-id-prefix=-UT341-
seed-ratio=0
# No this option in 1.15.2
#force-save=true
bt-hash-check-seed=true
bt-seed-unverified=true
bt-save-metadata=true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;running&quot;&gt;Running&lt;/h1&gt;

&lt;p&gt;Version 1.15.2 does not recognize default &lt;em&gt;$XDG_CONFIG_HOME/aria2/aria2.conf&lt;/em&gt; location. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--conf-path&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;aria2c &lt;span class=&quot;nt&quot;&gt;--conf-path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/.config/aria2/aria2.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpc-listen-port&lt;/code&gt; is allowed on &lt;em&gt;host&lt;/em&gt; by &lt;em&gt;iptables&lt;/em&gt; (on OpenWRT or PC). If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--rpc-listen-all&lt;/code&gt; is True, &lt;em&gt;aria2&lt;/em&gt; listens incoming JSON-RPC/XML-RPC requests on all network  interfaces. We can strict incoming requests to a specific interface by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d host-ip&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# iptables -t filter -A INPUT -p tcp --dport 6800 -j ACCEPT&lt;/span&gt;
or
&lt;span class=&quot;c&quot;&gt;# iptables -t filter -A INPUT -p tcp -m tcp -d host-ip --dport 6800 -j ACCEPT&lt;/span&gt;
or
&lt;span class=&quot;c&quot;&gt;# iptables -t nat -A WANPREROUTING -p tcp --dport 6800 -j DNAT --to-destination host-ip:6800&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# iptables -t filter -A INPUT -p tcp -m tcp -d host-ip --dport 6800 -j ACCEPT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;webui-aria2&quot;&gt;&lt;a href=&quot;https://github.com/ziahamza/webui-aria2&quot;&gt;webui-aria2&lt;/a&gt;&lt;/h1&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://github.com/gotbletu/shownotes/blob/master/webui_aria2c.md&quot;&gt;webui_aria2c&lt;/a&gt;. Remember that we set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enable-rpc=true&lt;/code&gt; above to manage &lt;em&gt;aria2&lt;/em&gt; on RPC interface. For example, you configure &lt;em&gt;aria2&lt;/em&gt; at home OpenWRT. You are in office and would like to file an AV download by webui interface.&lt;/p&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;h3 id=&quot;git-clone&quot;&gt;&lt;em&gt;git clone&lt;/em&gt;&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/workspace/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 https://github.com/ziahamza/webui-aria2.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;webui-aria2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;public-url&quot;&gt;Public URL&lt;/h3&gt;

&lt;p&gt;Visit &lt;a href=&quot;https://ziahamza.github.io/webui-aria2/&quot;&gt;Public URL&lt;/a&gt; and fill in &lt;em&gt;Settings -&amp;gt; Connection Settings&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;rpc-connection&quot;&gt;RPC connection&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The easiest way: visit the &lt;a href=&quot;https://ziahamza.github.io/webui-aria2/&quot;&gt;Public URL&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;If you don&apos;t trust the public URL like me, install webui manually.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Open &lt;em&gt;index.html&lt;/em&gt; in browser if cloned on access PC.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use Python &lt;em&gt;simplehttpserver&lt;/em&gt; to host the cloned webui. RPC listens at 6800 and we can set HTTP Server listens at 6801.&lt;/p&gt;

    &lt;p&gt;This is similar to the Pbulic URL but hosted by our own. You&apos;d better host the webui HTTP Server on PC, public IP (i.e. on VPS) or even on OpenWRT.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/workspace/webui-aria2
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; http.server 6801 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&amp;amp;
or
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python2 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; SimpleHTTPServer 6801 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Browse &lt;em&gt;http://localhost:6801&lt;/em&gt; or &lt;em&gt;http://ip_address_of_server:6801&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;connection-settings&quot;&gt;Connection Settings&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;If you access webui by &lt;em&gt;index.html&lt;/em&gt; or locally hosted HTTP Server, set &lt;em&gt;user&lt;/em&gt;, &lt;em&gt;pass&lt;/em&gt;, &lt;em&gt;host&lt;/em&gt; etc. in &lt;em&gt;configuration.js&lt;/em&gt; permanently.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/workspace/webui-aria2
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nano &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; configuration.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;These values can be changed on the webui HTML page afterwards.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If webui is hosted on public IP (VPS/OpenWRT), don&apos;t set those variables as it can be compromised. For example, if someone got your router IP and webui HTTP Server port, he could access to your &lt;em&gt;aria2&lt;/em&gt; daemon.&lt;/p&gt;

    &lt;p&gt;Instead, leave the &lt;em&gt;configuration.js&lt;/em&gt; alone and fill in values on webui page (like a web page logon).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;directurl&quot;&gt;&lt;em&gt;directurl&lt;/em&gt;&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;This feature allows users to download files that they download from aria2 directly from the webui dashboard.&lt;/li&gt;
  &lt;li&gt;Suppose &lt;em&gt;aria2&lt;/em&gt; is downloading on OpenWRT, &lt;em&gt;directurl&lt;/em&gt; generates clickable link to downloaded files on webui. Simplest way is to use Python to setup a HTTP server like the hosting webui page. webui listens at 6801 and we can let &lt;em&gt;directurl&lt;/em&gt; listens at 6802.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;This time, the HTTP Server must be hosted on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d, --dir&lt;/code&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/Downloads/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; http.server 6802 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&amp;amp;
or
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python2 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; SimpleHTTPServer 6802 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To test, just browse &lt;em&gt;http://serverip:6802&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;It should get a directory listing. Any browser errors and something hasn&apos;t been done properly, check IP/PORT etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Depend on your needs, set &lt;em&gt;directURL&lt;/em&gt; to &lt;em&gt;&apos;http://localhost:6802/&apos;&lt;/em&gt; in &lt;em&gt;configuration.js&lt;/em&gt;. Or set &lt;em&gt;Settings -&amp;gt; Connection Settings -&amp;gt; Enter base URL&lt;/em&gt; on webui page.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Make sure have the / on the end&lt;/em&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;After that, all downloaded file can be dragged to local computer (PC in use) on webui page.&lt;/li&gt;
  &lt;li&gt;[to be confirmed] Make sure port 6802 is also allowed by &lt;em&gt;iptables&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;The simplest Directurl is &lt;em&gt;file:///${HOME}/Downloads/&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;iptables&quot;&gt;Iptables&lt;/h1&gt;

&lt;p&gt;By default, everything works fine. But if &lt;em&gt;aria2&lt;/em&gt; does not work, check ports 6800, 6801, 6802, 6881-6999 etc. are allowed in Iptables.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;rpc-listen-port: default 6800;&lt;/li&gt;
  &lt;li&gt;webui and directurl HTTP Servers ports: 6801 and 6802;&lt;/li&gt;
  &lt;li&gt;listen-port: default TCP ports 6881-6999;&lt;/li&gt;
  &lt;li&gt;dht-listen-port: default UDP ports 6881-6999.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the OUTPUT chain, TCP/UDP 6881-6999 MUST be accepted:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-A OUTPUT -p tcp -m tcp --dport 6881:6999 -m conntrack --ctstate NEW -j ACCEPT
-A OUTPUT -p udp -m udp --dport 6881:6999 -m conntrack --ctstate NEW -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For the INPUT chain, it depends.&lt;/p&gt;

&lt;h1 id=&quot;scheme&quot;&gt;Scheme&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;aria2&lt;/em&gt; and webui are on the same host (OpenWRT/PC/VPS etc.).&lt;/li&gt;
  &lt;li&gt;They are on different hosts. For instance, &lt;em&gt;aria2&lt;/em&gt; is on OpenWRT while webui is hosted on VPS or PC.&lt;/li&gt;
  &lt;li&gt;If webui is on PC, I think there is no need to set up a separate HTTP Server for webui or &lt;em&gt;directurl&lt;/em&gt;. We can just open the &lt;em&gt;index.html&lt;/em&gt; from browser bookmark. And we can access our downloaded files directly on local PC.&lt;/li&gt;
  &lt;li&gt;We can add init script to load &lt;em&gt;aria2&lt;/em&gt; on boot (OpenWRT).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following setting is to run both &lt;em&gt;aria2&lt;/em&gt; and webui on PC.&lt;/p&gt;

&lt;h2 id=&quot;alias-on-pc&quot;&gt;Alias on PC&lt;/h2&gt;

&lt;p&gt;We need different set of arguments for different downloads. For example, to download PT resources, we should camouflage &lt;em&gt;aria2&lt;/em&gt; as &lt;em&gt;uTorrent&lt;/em&gt;. But options for PT impact BT download performance. We can set an alias for PT by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--conf-path&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nano &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;aria2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;aria2c --conf-path=${HOME}/.config/aria2/aria2.conf&apos;&lt;/span&gt;
or
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;aria2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;aria2c --conf-path=${HOME}/.config/aria2/aria2.conf; cd ${HOME}/Downloads/; python3 -m http.server 6802 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&amp;amp;&apos;&lt;/span&gt;
or
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;aria2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;aria2c --conf-path=${HOME}/.config/aria2/aria2.conf; cd ${HOME}/workspace/webui-aria2/; python3 -m http.server 6801 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&amp;amp; cd ${HOME}/Downloads/; python3 -m http.server 6802 &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&amp;amp;&apos;&lt;/span&gt;
or
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;aria2pt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;aria2c --conf-path=${HOME}/.config/aria2/aria2pt.conf&apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;launch-on-pc&quot;&gt;Launch on PC&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Launch RPC daemon&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type &lt;/span&gt;aria2c aria2 aria2pt
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;aria2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Open webui &lt;em&gt;index.html&lt;/em&gt; file or access &lt;em&gt;http://localhost:6802&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;issues&quot;&gt;Issues&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Magnet zero speed.&lt;/p&gt;

    &lt;p&gt;When downloading magnet files, there is no speed. This is due ot lack in &lt;em&gt;dht entry point&lt;/em&gt;. Details refer to &lt;a href=&quot;https://github.com/aria2/aria2/issues/504&quot;&gt;issue 504&lt;/a&gt;, &lt;a href=&quot;https://stackoverflow.com/q/1181301&quot;&gt;dht bootstrap nodes&lt;/a&gt;, and &lt;a href=&quot;http://forum.tinycorelinux.net/index.php?topic=17160.0&quot;&gt;aria2 and magnet links&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dht-entry-point&lt;/code&gt; as &lt;em&gt;dht.transmissionbt.com&lt;/em&gt;, &lt;em&gt;router.utorrent.com&lt;/em&gt; or &lt;em&gt;router.bittorrent.com&lt;/em&gt;. Port is 6881.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;browser-plugins&quot;&gt;Browser plugins&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;TO-DOs&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Plugins for BaiduYun.&lt;/li&gt;
  &lt;li&gt;Plugins to lauch &lt;em&gt;aria2&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://1024coder.com/topic/15&quot;&gt;VPS下使用aria2进行BT下载及其WebUi配置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/aa65535/5e956c4eb4f451ddec29&quot;&gt;Aria2的配置文件 &amp;amp; 启动脚本&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://aria2c.com/usage.html&quot;&gt;Aria2 &amp;amp; YAAW 使用说明&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.binux.me/2012/12/aria2-examples/&quot;&gt;aria2配置示例&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.librehat.com/aria2-camouflage-utorrent-pt-download/&quot;&gt;Aria2伪装uTorrent进行PT下载&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://tieba.baidu.com/p/2894158631&quot;&gt;aria2亦可以用于PT下载&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://kzpu.com/archives/3526.html&quot;&gt;Aria2伪装uTorrent进行PT下载&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/gotbletu/shownotes/blob/master/webui_aria2c.md&quot;&gt;webui config&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Enforce HTTPS to your site by Cloudflare</title>
   <link href="/2016/05/06/cloudflare-https/"/>
   <updated>2016-05-06T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/05/06/cloudflare-https</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#cloudflare&quot; id=&quot;markdown-toc-cloudflare&quot;&gt;Cloudflare&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#dns-switch&quot; id=&quot;markdown-toc-dns-switch&quot;&gt;DNS switch&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#cache-and-security&quot; id=&quot;markdown-toc-cache-and-security&quot;&gt;Cache and Security&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ssl-settings&quot; id=&quot;markdown-toc-ssl-settings&quot;&gt;SSL settings&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cache-all-the-things&quot; id=&quot;markdown-toc-cache-all-the-things&quot;&gt;Cache all the things&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#dnssec&quot; id=&quot;markdown-toc-dnssec&quot;&gt;DNSSEC&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#last-but-trivial&quot; id=&quot;markdown-toc-last-but-trivial&quot;&gt;Last but trivial&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#github-cdn-vs-cloudflare-cdn&quot; id=&quot;markdown-toc-github-cdn-vs-cloudflare-cdn&quot;&gt;GitHub CDN vs Cloudflare CDN&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#refs&quot; id=&quot;markdown-toc-refs&quot;&gt;Refs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By default, GitHub takes HTTPS protocol to user/project pages i.e. &lt;em&gt;username.github.io&lt;/em&gt;. However, for a custiomized domain, HTTPS is unsupported. This post tells us to enforce HTTPS to GitHub page through free Cloudflare services. Mainly, we just need to tune a few settings on Clouflare and your domain registrar.&lt;/p&gt;

&lt;p&gt;To be honest, Cloudflare&apos;s free CDN caching may slow down instead of accelerating your sites.&lt;/p&gt;

&lt;h1 id=&quot;cloudflare&quot;&gt;Cloudflare&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://www.cloudflare.com&quot;&gt;Cloudflare&lt;/a&gt; offers us free DNS and CDN services whilist concentrating on customer security. Those who would like to enforce HTTPS to his sites could take advantage of those services. For instance, Cloudflare will protect your site email address from web crawler.&lt;/p&gt;

&lt;p&gt;The detailed free services are listed below. To achieve HTTPS, only the first three is a must.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.cloudflare.com/introducing-universal-ssl/&quot;&gt;Free automatic HTTPS&lt;/a&gt; for your domain - no need to buy a certificate;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://support.cloudflare.com/hc/en-us/articles/200168306-Is-there-a-tutorial-for-Page-Rules-&quot;&gt;Page Rules&lt;/a&gt; - custom settings and redirects for URL patterns;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.cloudflare.com/enforce-web-policy-with-hypertext-strict-transport-security-hsts/&quot;&gt;HTTP Strict Transport Security (HSTS)&lt;/a&gt; - protection from MITM attacks;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cloudflare.com/dnssec/universal-dnssec/&quot;&gt;DNSSEC&lt;/a&gt; - protection from DNS poisoning attacks;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cloudflare.com/http2/&quot;&gt;HTTP/2&lt;/a&gt; - optimised connections for browsers that support it;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.cloudflare.com/introducing-cname-flattening-rfc-compliant-cnames-at-a-domains-root/&quot;&gt;CNAME flattening&lt;/a&gt; - so you can use a DNS CNAME at the domain apex;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cloudflare.com/always-online/&quot;&gt;&quot;Always online&quot;&lt;/a&gt; protection - Your cached website will stay up even if the host goes down;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cloudflare.com/features-security/&quot;&gt;Firewall&lt;/a&gt; - intelligent protection against DDOS attacks.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://support.cloudflare.com/hc/en-us/articles/200169466-Can-I-use-Cloudflare-with-WebSockets-&quot;&gt;websocket&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Require Modern TLS on Crypto tab.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We should register a Cloudflare account and then &lt;em&gt;add site&lt;/em&gt;. Follow the &lt;em&gt;add site&lt;/em&gt; procedure, we will finish the HTTPS enforcement. Before we go into details, we should clarify a few points:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;First, write down your custom GitHub page domain/sub-domain, i.e. &lt;em&gt;example.com&lt;/em&gt; or &lt;em&gt;blog.example.com&lt;/em&gt;. But top domain is recommended even you are using a sub-domain.&lt;/li&gt;
  &lt;li&gt;Find your domain registrar management interface, i.e. &lt;em&gt;www.freenom.com&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;In the domain management interface, find the setting of DNS servers and DNS records.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will basically do two things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Cloudflare imports DNS records and switch DNS servers to Cloudflare&apos;s.You may delete imported DNS records from &lt;em&gt;freenom&lt;/em&gt;, &lt;em&gt;namecheap&lt;/em&gt; etc.&lt;/li&gt;
  &lt;li&gt;Turn on a few security settings on Cloudflare. That&apos; all!&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;dns-switch&quot;&gt;DNS switch&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https://support.cloudflare.com/hc/en-us/articles/220981767-Can-I-add-a-subdomain-on-CloudFlare-&quot;&gt;Subdomains cannot be added on their own&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;After filling in your site url following &lt;em&gt;add site&lt;/em&gt; procedure, Cloudflare will analyze and import the site&apos;s DNS records (from your previous platforms).&lt;/p&gt;

    &lt;p&gt;We can add, delete a new DNS records. Even, we can toggle Cloudflare per a record.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Then continue, Cloudflare will give us two new Cloudflare DNS servers.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Go to our domain registrar management interface, and replace all original DNS servers with the new ones.&lt;/p&gt;

    &lt;p&gt;To make use of Cloudflare service, all other platforms&apos; DNS servers must be deleted. Only Cloudflare ones are permitted.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Up to now, Cloudflare takes over DNS servers and DNS records management.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;cache-and-security&quot;&gt;Cache and &lt;a href=&quot;https://security.stackexchange.com/a/151572&quot;&gt;Security&lt;/a&gt;&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Cloudflare as a man in the middle (MITM)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By default, Cloudflare accelerate and protect (i.e. cache files) sites (an orange cloud symbol at the end of DNS record).&lt;/p&gt;

&lt;p&gt;You may want to disable that functionality for specific sub-domains like &lt;em&gt;irc.example.com&lt;/em&gt;. For example, local ISP blocks Cloudflare CDN servers. On the other hand you lose the free services mentioned above.&lt;/p&gt;

&lt;p&gt;Alternatively, it hides web site&apos;s original location (i.e. IP). Refer to post V2ray for details. You can check by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dig&lt;/code&gt; your domain and find IP changed to that of Cloudflare&apos;s CDN servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ATTENTION&lt;/strong&gt;: Cloudflare decrypts all traffic from browser and negotiate new TLS with destination server. It is common that a CDN platform just uses HTTP. Hence, we cache static web pages or public multimedia. For confidential communication like password login, please &lt;strong&gt;avoid&lt;/strong&gt; CDN.&lt;/p&gt;

&lt;h1 id=&quot;ssl-settings&quot;&gt;SSL settings&lt;/h1&gt;

&lt;p&gt;Unfortunately GitHub doesn&apos;t yet support SSL for custom domains which would ordinarily rule out using HTTP/2. Whilst the HTTP/2 specification (RFC 7540) allows for HTTP/2 over plain-text HTTP/2, all popular browsers require HTTP/2 to run on top of Transport Layer Security; meaning HTTP/2 only being able to run over HTTPS is the de facto standard.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;In the Crypto tab of your CloudFlare site you should ensure your SSL mode is set to &lt;em&gt;Full&lt;/em&gt; but not &lt;em&gt;Full (strict)&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We can now add a Page Rule to enforce HTTPS, as you add other Page Rules make sure this is the primary Page Rule:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://*example.com/*

Always Use HTTPS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Page rule happens &lt;em&gt;before&lt;/em&gt; DNS record resolving.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We can also create a Page Rule to ensure that &lt;em&gt;apex&lt;/em&gt; is redirected to www securely when using HTTPS:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;example.com/*

Forwarding URL (Status Code: 301 - Permanent Redirect)

https://www.example.com/$1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This rule should sit &lt;a href=&quot;https://support.cloudflare.com/hc/en-us/articles/218411427#overview&quot;&gt;before the previous one&lt;/a&gt; since it&apos;s more &lt;em&gt;specific&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Back to the Crypto tab, enable and set HTTP Strict Transport Security (HSTS) service. HSTS (RFC 6797) is a header which allows a website to specify and enforce security policy in client web browsers.&lt;/p&gt;

    &lt;p&gt;The recommended settings are:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Status: On
Max-Age: 6 months (recommended)
Include subdomains: On
Preload: On
No-sniff: On
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;That&apos;s all.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Test&lt;/p&gt;

    &lt;p&gt;Though we should wait for a while (hours maybe) to acccess GitHub pages over HTTPS, we can test security settings by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -I example.com&lt;/code&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;HTTP/1.1 301 Moved Permanently
Date: Mon, 12 Sep 2016 11:14:57 GMT
Connection: keep-alive
Set-Cookie: __cfduid=afj4n38eahdglvmneuptoq84h; expires=Tue, 12-Sep-17 11:14:57 GMT; path=/; domain=.exmaple.com; HttpOnly
Location: https://example.com/
X-Content-Type-Options: nosniff
Server: cloudflare-nginx
CF-RAY: 3fien1q9ehpen-HKG
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Disable SSL&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt;: if you decide to disable SSL for whatever causes, please disable HSTS &lt;strong&gt;before&lt;/strong&gt; HTTPS.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;cache-all-the-things&quot;&gt;Cache all the things&lt;/h1&gt;

&lt;p&gt;CloudFlare has a “Cache Everything” option in Page Rules. For static sites, it allows your HTML to be cached and served directly from CloudFlare&apos;s CDN. This will significantly accelerate your site access time.&lt;/p&gt;

&lt;p&gt;Add a last rule as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://*example.com/*

Cache Level: Cache Everything
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When deploying your site you can use the Purge Cache option in the Cache tab on CloudFlare to remove the cached version of the static pages.&lt;/p&gt;

&lt;h1 id=&quot;dnssec&quot;&gt;DNSSEC&lt;/h1&gt;

&lt;p&gt;If DNS is the phone book of the Internet, DNSSEC is the protocol that ensures that a number in the phone book actually belongs to the contact listed. DNSSEC uses cryptographic signatures to verify that the DNS records returned for a domain are untampered.&lt;/p&gt;

&lt;p&gt;If your domain registrar support DNSSEC, please turn on DNSSEC on Cloudflare DNS tab.&lt;/p&gt;

&lt;h1 id=&quot;last-but-trivial&quot;&gt;Last but trivial&lt;/h1&gt;

&lt;p&gt;As shown above, to turn on HTTPS, we just tune a few settings, leaving the GitHub page sources untouched.&lt;/p&gt;

&lt;p&gt;But we should at least change the &lt;em&gt;url&lt;/em&gt; variable in &lt;em&gt;_config.yml&lt;/em&gt; to its HTTPS version.&lt;/p&gt;

&lt;h1 id=&quot;github-cdn-vs-cloudflare-cdn&quot;&gt;GitHub CDN vs Cloudflare CDN&lt;/h1&gt;

&lt;p&gt;Without Cloudflare, GitHub supports CDN as well and default GitHub page acces time is trivial. However, Cloudflare offers extra HTTPS service.&lt;/p&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.cloudflare.com/secure-and-fast-github-pages-with-cloudflare/&quot;&gt;Cloudflare blog&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://robinwinslow.uk/2016/02/13/free-https-custom-hosting/&quot;&gt;robinwinslow&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://sheharyar.me/blog/free-ssl-for-github-pages-with-custom-domains/&quot;&gt;sheharyar&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>TCP Obfuscation - ptproxy</title>
   <link href="/2016/04/12/ptproxy/"/>
   <updated>2016-04-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/04/12/ptproxy</id>
   <content type="html">&lt;s&gt;ptproxy&lt;/s&gt;
&lt;p&gt;is almost dead. The repository is ancient whilist &lt;em&gt;aisocks&lt;/em&gt; has dropped support for Python 3.4! Try &lt;a href=&quot;https://github.com/shadowsocks/simple-obfs&quot;&gt;simple obfs&lt;/a&gt; instead!&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/gumblex/ptproxy&quot;&gt;ptproxy&lt;/a&gt; (&lt;a href=&quot;https://gumble.tk/ptproxy.html&quot;&gt;author page&lt;/a&gt;) obfuscates TCP traffic with the help of Tor&apos;s PT (&lt;a href=&quot;/2016/02/28/tor/&quot;&gt;pluggable transports&lt;/a&gt;) prototol. This tool is independent of Tor and applies to any TCP traffic. In this post, I demonstrate how &lt;em&gt;ptproxy&lt;/em&gt; obfuscate Shadowsocks traffic.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;To speed up TCP connection to VPS, try &lt;a href=&quot;https://github.com/xtaci/kcptun&quot;&gt;KCPtun&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Before &lt;em&gt;ptproxy&lt;/em&gt;&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;app -&amp;gt; Shadowsocks client -&amp;gt; Shadowsocks server -&amp;gt; destination host&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;With &lt;em&gt;ptproxy&lt;/em&gt;&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;app -&amp;gt; Shadowsocks client -&amp;gt; ptproxy client -&amp;gt; ptproxy server -&amp;gt;  Shadowsocks server -&amp;gt; destination host&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;In proxy chain, there are client/server node pairs. But each node (named as client or server) actually plays another pair of client/server functionalities at the same instant/simutaneously/concurrently. Each node forwards requests while listens for incoming request.&lt;/p&gt;

    &lt;p&gt;The former client/server refer to literal name of chain node, while the later pair are that node&apos;s functionalities. A server functionality address is set at your will while a client functionality address must be set to address a server functionality.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;In this post, assume client resides on localhost while servers resides on VPS.&lt;/li&gt;
  &lt;li&gt;New &lt;strong&gt;Async&lt;/strong&gt; version requirs &lt;em&gt;&amp;gt;=python=3.4&lt;/em&gt;. The ancient shell script version is deprecated.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;python34-on-centos-65&quot;&gt;Python3.4 on CentOS 6.5&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd /var/tmp&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# wget https://www.python.org/ftp/python/3.4.4/Python-3.4.4.tgz&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# tar vxzf Python-3.4.4.tgz&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cd Python-3.4.4&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ./configure --prefix=/usr/local/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# make &amp;amp;&amp;amp; make altinstall&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# python3.4 -V&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ln -sv /usr/local/bin/python3.4 /usr/bin/python3.4&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rm Python-3.4.4.tgz&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;configuration-sample&quot;&gt;Configuration sample&lt;/h1&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1:1080&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0.0.0.0:23456&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptexec&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;obfs4proxy -logLevel ERROR -enableLogging&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptname&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;obfs4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptargs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cert=AAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;iat-mode=0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptserveropt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptproxy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;It&apos;s localhost part (client) and VPS part (server).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A directory to store &lt;em&gt;ptproxy&lt;/em&gt; running states consisting of several Json files.&lt;/p&gt;

    &lt;p&gt;We should modify &lt;em&gt;obfs4_state.json&lt;/em&gt; to switch &lt;em&gt;iat-mode&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;local&lt;/em&gt; literally must be a &lt;em&gt;loopback&lt;/em&gt; address (&lt;em&gt;127.0.0.1:port&lt;/em&gt;), traffic within localhost.&lt;/p&gt;

    &lt;p&gt;For &lt;em&gt;ptproxy client&lt;/em&gt; role, the loopback address is set (at your will) listening for local request. But for &lt;em&gt;ptproxy server&lt;/em&gt;, it is an address to which traffic is forwarded.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Similarly, &lt;em&gt;server&lt;/em&gt; parameter should be an address for remote connection.&lt;/p&gt;

    &lt;p&gt;For &lt;em&gt;ptproxy client&lt;/em&gt; role, the remote address is set to &lt;em&gt;ptproxy server&lt;/em&gt;&apos;s listening address on VPS which is, in return, equal to &lt;em&gt;ptproxy server&lt;/em&gt;&apos;s &lt;em&gt;server&lt;/em&gt; argument.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;That&apos;s the &lt;em&gt;pluggable transport&lt;/em&gt; executable.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;ptname&lt;/em&gt; should be unique for each &lt;em&gt;ptproxy&lt;/em&gt; client/server pair.&lt;/li&gt;
  &lt;li&gt;For &lt;em&gt;ptproxy&lt;/em&gt; server, ignore this.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;ptserveropt&lt;/em&gt; and &lt;em&gt;ptproxy&lt;/em&gt; are usually left alone.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;server&quot;&gt;Server&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Get &lt;em&gt;ptproxy&lt;/em&gt;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd /opt/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# git clone --branch master --depth 1 https://github.com/gumblex/ptproxy.git&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# git clone --branch master --depth 1 https://github.com/nibrag/aiosocks.git&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cd ptproxy/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ln -sv /opt/aiosocks/aiosocks aiosocks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;I don&apos;t like 3rd-party code snippets (Aiosocks here) mingled with system packages. Just put it together with &lt;em&gt;ptproxy&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Server configuration&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd ptproxy&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cp example.json server.json&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vim server.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;ptproxy&lt;/em&gt; server listens on VPS for incoming &lt;em&gt;ptproxy&lt;/em&gt; client traffic while forwards that to Shadowsocks server.&lt;/p&gt;

    &lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/ptproxy/pt_state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1:5555&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0.0.0.0:5554&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptexec&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/bin/obfs4proxy -logLevel ERROR -enableLogging&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptname&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;obfs4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptargs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cert=AAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;iat-mode=0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptserveropt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptproxy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;The &lt;em&gt;json&lt;/em&gt; configuration file does not allow comments. Remove them before launching.&lt;/li&gt;
      &lt;li&gt;Do NOT use bash reserving words in configuration, i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${HOME}&lt;/code&gt; which is unkown to &lt;em&gt;ptproxy&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Initial server startup&lt;/p&gt;

    &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# cd /opt/ptproxy/&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# mkdir pt_state; chown -R nobody: pt_state&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# su nobody -s /bin/bash -c &quot;python3.4 ptproxy.py -s server.json&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Must make sure &lt;em&gt;nobody&lt;/em&gt; has &lt;em&gt;write&lt;/em&gt; access to &lt;em&gt;pt_state&lt;/em&gt; directory.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;This is the very first launch. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;su nobody -s /bin/bash&lt;/code&gt; drop user to &lt;em&gt;nobody&lt;/em&gt; instead of &lt;em&gt;root&lt;/em&gt;. Useful information is printed on stdout for client side.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2015-10-02 18:16:49 Starting PT…
===== Server information =====
“server&quot;: “xxx.xxx.xxx.xxx:yyy&quot;,
“ptname&quot;: “obfs4″,
“ptargs&quot;: “cert=xxxxxxxxxxxxxxxxxxxxxxxxxxxxx;iat-mode=0″,
==============================
2015-10-02 18:16:49 PT started successfully.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Meanwhile three state files are generated under &lt;em&gt;/opt/ptproxy/pt_state&lt;/em&gt;. &lt;em&gt;obfs4_state.json&lt;/em&gt; need modification for &lt;em&gt;iat-mode&lt;/em&gt;, which means &lt;em&gt;inter-arrival time&lt;/em&gt; controlling whether to confuscate packets&apos; sending time by padding bits. By default, it is turned off.&lt;/p&gt;

    &lt;p&gt;In order to be more robust, change to 1 (Enabled, ScrambleSuit-style with bulk throughput optimizations) or 2 (Paranoid, Each IAT write will send a length sampled from the length distribution. This may slow down performance). Details refer to &lt;a href=&quot;https://lists.torproject.org/pipermail/tor-commits/2014-August/079402b.html&quot;&gt; Various IAT related changes&lt;/a&gt;. &lt;em&gt;iat-mode&lt;/em&gt; of Tor bridges is turned off by default either.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;iat-mode&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;To modify &lt;em&gt;obfs4_state.json&lt;/em&gt;, the running instance must be killed first.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# pkill -f &quot;ptproxy.py&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Attention, on the server side, modify &lt;em&gt;obfs4_state.json&lt;/em&gt;. Leave &lt;em&gt;server.json&lt;/em&gt; alone.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Real launch by &lt;em&gt;rc.local&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;Add to &lt;em&gt;/etc/rc.local&lt;/em&gt; (symlink to &lt;em&gt;/etc/rc.d/rc.local&lt;/em&gt;) on CentOS:&lt;/p&gt;

    &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# /etc/rc.local&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/ptproxy&quot;&lt;/span&gt;
/bin/su nobody &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /bin/bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/python3.4 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/ptproxy.py -s &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/server.json &amp;amp;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;To check the shell syntax, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set -x&lt;/code&gt; to the beginning of &lt;em&gt;rc.local&lt;/em&gt; and &lt;em&gt;sh /etc/rc.local&lt;/em&gt;. Errors will be printed.&lt;/p&gt;

    &lt;p&gt;If this is the only shell commands in &lt;em&gt;rc.local&lt;/em&gt;, just execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sh /etc/rc.local&lt;/code&gt;. Otherwise, reboot VPS. It&apos;s not recommended to launch &lt;em&gt;ptproxy&lt;/em&gt; server directly on SSH terminal, which may result in service killed occasionally.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ptproxy-client&quot;&gt;&lt;em&gt;ptproxy&lt;/em&gt; client&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd /opt/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# git clone --branch master --depth 1 https://github.com/gumblex/ptproxy.git&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# git clone --branch master --depth 1 https://github.com/nibrag/aiosocks.git&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cd ptproxy/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ln -sv /opt/aiosocks/aiosocks aiosocks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Client configuration&lt;/p&gt;

    &lt;p&gt;Edit &lt;em&gt;ss-client.json&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;client&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/ptproxy/pt_state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1:5553&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ip-of-vps:5554&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptexec&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/bin/obfs4proxy -logLevel ERROR -enableLogging&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptname&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;obfs4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptargs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cert=AAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;iat-mode=0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptserveropt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;ptproxy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The &lt;em&gt;ptname&lt;/em&gt; and &lt;em&gt;ptargs&lt;/em&gt; should be set according to the initial server launch output. If choose to change &lt;em&gt;iat-mode&lt;/em&gt;, remember to update local &lt;em&gt;obfs4_state.json&lt;/em&gt; as well.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Shadowsocks client&apos;s side configuration&lt;/p&gt;

    &lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;server_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5553&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local_address&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;local_port&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1080&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;password&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;gh1Tsy71nw&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;timeout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;method&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;aes-256-cfb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;fast_open&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Change the &lt;em&gt;server&lt;/em&gt; and &lt;em&gt;server_port&lt;/em&gt; to &lt;em&gt;ptproxy&lt;/em&gt;&apos;s counterparts.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Iptables&lt;/p&gt;

    &lt;p&gt;Turn on &lt;em&gt;ptproxy&lt;/em&gt;&apos;s server listening port&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# iptables -t nat -I OUTPUT 4 -d server-ip -p tcp -m multiport --dports 5554,5555 -j RETURN
# iptables -I OUTPUT 5 -d server-ip -p tcp -m multiport --dports 5554,5555 -j RETURN
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;5555 is Shadowsocks server port (just in case we turn off &lt;em&gt;ptproxy&lt;/em&gt;) while 5554 is &lt;em&gt;ptproxy&lt;/em&gt; server port.&lt;/p&gt;

    &lt;p&gt;Choose the -I &lt;em&gt;rulenum&lt;/em&gt; based on your case.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Client startup&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd ~/ptproxy/ptproxy&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# su nobody -s /bin/bash -c &quot;python3.4 ptproxy.py -c client.json&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Client startup script&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/sbin/openrc-run&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# To obfsucating TCP traffic, esepcially for SOCKS5 Shadowsocks&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/opt/ptproxy&quot;&lt;/span&gt;

depend&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  after net.wlp3s0
  after net.enp0s25
  after dhcpcd
  before shadowsocks
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

start&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;RC_CMD&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;restart&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;ebegin &lt;span class=&quot;s2&quot;&gt;&quot;Waiting&quot;&lt;/span&gt;
    eend &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi

  &lt;/span&gt;ebegin &lt;span class=&quot;s2&quot;&gt;&quot;Starting ptproxy&quot;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; pgrep &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; nobody &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/python3.4 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/ptproxy.py -c &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/client.json&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;su nobody &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /bin/bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/python3.4 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/ptproxy.py -c &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/client.json &amp;gt;/dev/null &amp;amp;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi

  &lt;/span&gt;eend &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

stop&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  ebegin &lt;span class=&quot;s2&quot;&gt;&quot;Stoping ptproxy&quot;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;pgrep  &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; nobody &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/python3.4 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/ptproxy.py -c &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/client.json&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;pkill &lt;span class=&quot;nt&quot;&gt;-TERM&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; nobody &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/python3.4 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/ptproxy.py -c &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PT_DIR&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/client.json&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi

  &lt;/span&gt;eend &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;It&apos;s recommended to merge this init script with Shadowsocks init script.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;notes&quot;&gt;Notes&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;A &lt;em&gt;ptproxy&lt;/em&gt; client instance is associated with a server instance by argument &lt;em&gt;ptname&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;That is to say, a client/server pair are for one application&apos;s TCP obfuscation (Shadowsocks in this post).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If want to obfuscate another application&apos;s TCP traffic, we should launch another pair of client/server instances with a new pair of client/server configuration files.&lt;/p&gt;

    &lt;p&gt;Specially, change the &lt;em&gt;state&lt;/em&gt; location. We may use another PT binary like &lt;em&gt;obfsproxy/obfs3&lt;/em&gt;. We also should choose new port client/server ports etc. Most important, choose new &lt;em&gt;ptname&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;If Tor is used with Bridges and PT. Likely an instance of &lt;em&gt;obfsproxy/obfs4proxy&lt;/em&gt; exists on you local host. This time the Tor serves &lt;em&gt;ptproxy&lt;/em&gt;&apos;s role.&lt;/li&gt;
  &lt;li&gt;Run as &lt;em&gt;nobody&lt;/em&gt;:
    &lt;ol&gt;
      &lt;li&gt;su nobody -s /bin/bash -c &quot;script here&quot;;&lt;/li&gt;
      &lt;li&gt;Make sure &lt;em&gt;nobody&lt;/em&gt; have &lt;em&gt;write&lt;/em&gt; access to &lt;em&gt;pt_state&lt;/em&gt; directory.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/gumblex/ptproxy&quot;&gt;ptproxy.git&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gumble.tk/ptproxy.html&quot;&gt;author page&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.590103.idv.tw/blog/%E5%9C%A8win7%E4%B8%AD%E5%88%A9%E7%94%A8ptproxy%E5%92%8Cobfs4proxy%E6%B7%B7%E8%82%B4shadowsocks%E9%80%A3%E7%B7%9A&quot;&gt;win7 config&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://briteming.blogspot.com/2015/08/obfs4proxy-shadowsocks.html&quot;&gt;ptproxy + obfsproxy/scramblesuit&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Email</title>
   <link href="/2016/04/01/email/"/>
   <updated>2016-04-01T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/04/01/email</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;The only security guarantee is setting your own Email server at home.&lt;/li&gt;
  &lt;li&gt;A/I and Riseup are relatively safer among the others.&lt;/li&gt;
  &lt;li&gt;A/I unlimited storage; up to 5 alias with many domain choices.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Riseup can change account name any time; 192MiB at most; unlimited alias with only Riseup domain.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Notice&lt;/em&gt;: if change account name, please add a alias for original account name. Otherwise you would not receive emails to that address.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;[doubt] A/I seems to be safer than Riseup.&lt;/li&gt;
  &lt;li&gt;Main address: the email address assigned when registering account. For both sending and receving emails.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Identity: address for sending emails; the From header.&lt;/p&gt;

    &lt;p&gt;Some email providers does not support unrecognized or unregistered identity From address. Though you can use identity address to spoof From header, most of time, your main address is still exposed in the mail source.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Alias: address for receiving emails; the To header.&lt;/p&gt;

    &lt;p&gt;If the identity does not have a corresponding alias, the receivers could not reply email unless you specify the Reply-To header. You can set a (identity, alias) pair and make sure the address pair be a legal provider email address.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Notice&lt;/strong&gt;: if your spoofed identity From address is owned by somebody else (main address or alias), the reply email will go to his mail box! DANGEROUS!&lt;/p&gt;

    &lt;p&gt;So when setting spoof From header, use one of your alias.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Main address just for account management (i.e. IMAP/SMTP authentication); does not expose main account on the Internet, especially do not register other online service with main address.&lt;/li&gt;
  &lt;li&gt;Set up alias to register other online service (receiving emails); can be exposed online for others reaching you.&lt;/li&gt;
  &lt;li&gt;If you really want to disguise identity when sending emails, use a customized identity address. The specified identity address might be constrained by your email provider (i.e. must be of their valid email domain).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This can be done easily in Gnus, just change From header. In SquirrelMail, just add identities in Options.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;When forwarding Gmail to another account, by default Spam emails are left at the original account. The main idead is creating a filter to include Spam emails since Gmail filters are applied before Spam check.&lt;/p&gt;

    &lt;p&gt;The first method is dropping forwarding but create the filter like this:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Has the words deliveredto:your_incoming_address@gmail.com
Forward it to your_destination_address@example.com
Never send it to spam
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Another method is applying the filter before forwarding:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Has the words: is:spam or label:spam or in:spam
Never send it to Spam
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Email graph&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/email_graph.jpg&quot; alt=&quot;Email graph&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Proxy</title>
   <link href="/2016/03/08/proxy/"/>
   <updated>2016-03-08T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/03/08/proxy</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Real proxy&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;ss (Shadowsocks), Tor, VPN, GAE, SSH tunnel etc.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Real proxy listens on a specific &lt;em&gt;[IP[:port]]&lt;/em&gt; for incoming request.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Torify/Proxychains - direct traffic from shell&lt;/p&gt;

    &lt;p&gt;Torify (based on &lt;em&gt;torsocks&lt;/em&gt;) forces &lt;em&gt;tcp&lt;/em&gt; traffic through Tor for applications without built-in proxy support (including those not supporting SOCKS proxy).&lt;/p&gt;

    &lt;p&gt;Unfortunately, &lt;em&gt;torify/torsocks&lt;/em&gt; is only for Tor. Proxychains is more powerful supporingt any SOCKS4a/5 or HTTP proxies. It works in &lt;em&gt;dynamic&lt;/em&gt;, &lt;em&gt;exact&lt;/em&gt;, or &lt;em&gt;random&lt;/em&gt; modes. Also, it&apos;s fairly easy to define a chain of proxies - multiple proxies.&lt;/p&gt;

    &lt;p&gt;We can create a simple &lt;em&gt;.desktop&lt;/em&gt; file with prefix &lt;em&gt;torify/usewithtor/torsocks/proxychains&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;For command line tool without GUI (i.e. &lt;em&gt;wget&lt;/em&gt;), we just launch a sub-shell by &lt;em&gt;torify bash&lt;/em&gt; and &lt;em&gt;proxychains bash&lt;/em&gt;, under which all traffic goes through proxy - &lt;em&gt;to proxify a shell&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;A step further, add that command to &lt;em&gt;.bash_profile&lt;/em&gt; (login shell) or &lt;em&gt;.bashrc&lt;/em&gt; (interactive shell). Or &lt;em&gt;torify/proxychains xfce4-terminal&lt;/em&gt;. Each new shell is proxified.&lt;/p&gt;

    &lt;p&gt;Attention, &lt;em&gt;proxychains&lt;/em&gt; cannot not capture child process traffic. What was worse, &lt;a href=&quot;https://github.com/rofl0r/proxychains-ng/issues/116&quot;&gt;detached GUI&lt;/a&gt; traffic cannot be caught either.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Assistant proxy - direct traffic from application&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Privoxy, Foxyproxy, Autoproxy etc.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Assistant proxy only forwards application&apos;s traffic reqeust to real proxy. Defines which traffic uses proxy and which traffic does not. For example, Foxyproxy can add a PAC list forwarding traffic to real proxy.&lt;/p&gt;

    &lt;p&gt;Privoxy is a non-caching &lt;em&gt;web&lt;/em&gt; proxy with advanced filtering capabilities for enhancing privacy, modifying web page data and HTTP headers, controlling access, and removing ads and other obnoxious Internet junk. Privoxy has a flexible configuration and can be customized to suit individual needs and tastes. It has application for both stand-alone systems and multi-user networks:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Do NOT provide proxy functionality itself but forward HTTP traffic to other proxies, i.e. Tor, Shadowsocks, GAE etc.&lt;/li&gt;
      &lt;li&gt;Applications should support HTTP proxy, i.e. browser, instant messager etc.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Iptables - direct traffic through kernel.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SS alone as a SOCKS proxy. Add SS to Tor as a &lt;em&gt;front end&lt;/em&gt; proxy if no &lt;em&gt;Bridges&lt;/em&gt; are available.&lt;/p&gt;

    &lt;p&gt;Both are SOCKS proxy. Only applications (i.e. Firefox) that support SOCKS proxy can make use of them.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Foxyproxy and Autoproxy are browser extensions while Privoxy is stand alone application. Therefore Privoxy can serve all applications (besides browser) that support HTTP proxy.&lt;/p&gt;

    &lt;p&gt;Details on how to use Privoxy, refer to the 1st reference. For example, by Privoxy, we can direct &lt;em&gt;youtube.com&lt;/em&gt; traffic to GAE, while &lt;em&gt;sex.com&lt;/em&gt; traffic to Tor. Another vantange of privoxy is you can filter traffic based on &lt;em&gt;domain name&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Currently on my system, no extra applications (except browser) that support HTTP proxy needs proxy help. Firefox Foxyproxy has &lt;em&gt;whitelist&lt;/em&gt; and &lt;em&gt;blacklist&lt;/em&gt; applied to proxy. Turn on &lt;em&gt;Use proxies based on their pre-defined patterns and priorities&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Of course, if Privoxy is used, just add a new HTTP proxy entry (Privoxy default 127.0.0.1:8118) to Foxyproxy.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Iptables&lt;/p&gt;

    &lt;p&gt;Each Iptables rule is strict (specific TCP/IP values) but has wide match (many applications). An exetreme example, is forceing all system traffic to Tor/SS.&lt;/p&gt;

    &lt;p&gt;One utility is Transparent proxy. At TCP/IP level, REDIRECT all system traffic to Tor, thus avoiding other supporting tools (Torify, Assistant proxy etc.). Additionally, we can place some traffic rule ahead of the Transparent proxy rule to not use Tor - achieving whitelist.&lt;/p&gt;

    &lt;p&gt;Details refer to newest Iptables rule.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;One special case:&lt;/p&gt;

    &lt;p&gt;In Foxyproxy, select to use Shadowsocks for all URLs. In Iptables, enable Transparent proxy! The actual traffic path:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Foxyproxy modify HTTP packet to enclosed in Shadowsocks SOCKS packet;&lt;/li&gt;
      &lt;li&gt;Iptables Transparent proxy. To establish Tor circuit;&lt;/li&gt;
      &lt;li&gt;Shadowsocks front end proxy - Tor entry node - Tor middle nodes - Tor exit node;&lt;/li&gt;
      &lt;li&gt;Shadowsocks SOCKS packet - target URL.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;So Shadowsocks is access twice in the traffic path. And target website actually sees Shadowsocks accessing its service. To avoid this, add a Iptables rule:&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-A OUTPUT -d ss-ip -p tcp -m tcp --dport ss-port -j RETURN&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If network connection fails, check:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Real proxy, Torify/Torsocks, Assistant proxy, Iptables etc.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;Refs:
    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;https://program-think.blogspot.com/2014/12/gfw-privoxy.html&quot;&gt;如何用 Privoxy&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Gentoo Networking</title>
   <link href="/2016/03/01/networking/"/>
   <updated>2016-03-01T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/03/01/networking</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Discuss networking configuration in Gentoo system, covering &lt;em&gt;net.*&lt;/em&gt; config, dhcpcd, wpa_supplciant, mac spoofing etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Wireless, PPP etc. special networking needs &lt;em&gt;extra configuration&lt;/em&gt; before DHCP or static IP.&lt;/p&gt;

    &lt;p&gt;For example, before the wireless interface request IP from DHCP server, it must first authenticate username and password with wireless router. Otherwise, it was not even attched to a physical link. This functionality can be achieved by tools like &lt;em&gt;wpa_supplicant&lt;/em&gt; and/or &lt;em&gt;wireless-tools&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;The Gentoo traditional &lt;em&gt;net config&lt;/em&gt; is &lt;em&gt;/etc/init.d/net.*&lt;/em&gt; and &lt;em&gt;/etc/conf.d/net&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A functionality is not confined to a specific tool.&lt;/p&gt;

    &lt;p&gt;For instance, the wireless authentication functionality can be also achieved by &lt;em&gt;wcid&lt;/em&gt;, &lt;em&gt;networkmanager&lt;/em&gt; etc. as they all draw in &lt;em&gt;wpa_supplicant&lt;/em&gt; package.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A tool is not constrained to a specific funciontality. Most of the time, we only need a few of them.&lt;/p&gt;

    &lt;p&gt;For example, &lt;em&gt;dhcpcd&lt;/em&gt; can handle all networking functinalities.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;If using &lt;em&gt;net config&lt;/em&gt; or &lt;em&gt;dhcpcd&lt;/em&gt;, we should install &lt;em&gt;wpa_supplicant&lt;/em&gt; manually to satisfy wireless authentication.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;net config&lt;/em&gt; thing is Gentoo&apos;s own networking configuration scripts.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;simple-config&quot;&gt;Simple config&lt;/h1&gt;

&lt;p&gt;The simplest config on my system is &lt;em&gt;dhcpcd&lt;/em&gt; + &lt;em&gt;wpa_supplicant&lt;/em&gt;, though &lt;em&gt;net config + wpa_supplicant&lt;/em&gt; is fine. For Ethernet, &lt;em&gt;dhcpcd&lt;/em&gt; is enough! The extra &lt;em&gt;wpa_supplicant&lt;/em&gt; fullfils wireless authentication.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Emerge both packages;&lt;/li&gt;
  &lt;li&gt;Add &lt;em&gt;dhcpcd&lt;/em&gt; to &lt;em&gt;default&lt;/em&gt; runlevel; Don&apos;t add &lt;em&gt;wpa_supplicant&lt;/em&gt; to any runlevel.&lt;/li&gt;
  &lt;li&gt;Conigure &lt;em&gt;wpa_\supplicant.conf&lt;/em&gt; for authentication.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bingo~&lt;/p&gt;

&lt;h2 id=&quot;dhcpcd&quot;&gt;&lt;em&gt;dhcpcd&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;dhcpcd&lt;/em&gt; brings along its own &lt;em&gt;hooks&lt;/em&gt; (&lt;em&gt;/lib/dhcpcd/dhcpcd-hooks/&lt;/em&gt; and &lt;em&gt;/usr/share/dhcpcd/hooks/&lt;/em&gt;), like &lt;em&gt;resolv.conf&lt;/em&gt;, &lt;em&gt;wpa_supplicant&lt;/em&gt; etc. The hook tells &lt;em&gt;dhcpcd&lt;/em&gt; to launch a relevant service. For example, &lt;em&gt;wpa_supplicant&lt;/em&gt; hooks instruct &lt;em&gt;dhcpcd&lt;/em&gt; to launch &lt;em&gt;wpa_supplicant&lt;/em&gt; functionality before DHCP session.&lt;/p&gt;

&lt;p&gt;Now, &lt;em&gt;dhcpcd&lt;/em&gt; won&apos;t enable some hooks (i.e. &lt;em&gt;wpa_\supplicant&lt;/em&gt; ) by default, we need to copy the hook from &lt;em&gt;/usr/share/dhcpcd/hooks/&lt;/em&gt; to &lt;em&gt;/lib/dhcpcd/dhcpcd-hooks/&lt;/em&gt;. To disable a hook is trivial - either remove the hook under &lt;em&gt;/lib/dhcpcd/dhcpcd-hooks/&lt;/em&gt; or append &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nohook hook-name1, hook-name2&lt;/code&gt; to &lt;em&gt;/etc/dhcpcd.conf&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here is an excerpt of &lt;em&gt;dhcpcd&lt;/em&gt; config:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# stop resolv.conf hook to alter /etc/resolv.conf file since we will use TorDNS
# Another method is to remove /lib/dhcpcd/dhcpcd-hooks/20-reslve.conf hook
#
# Let net.wlan0 handle wpa_supplicant
nohook resolv.conf, wpa_supplicant

# Speed up DHCP by disabling ARP probing. This is useful in home network where IP collision
# rarely happens
noarp

# dhcpcd will release the lease prior to stopping the interface
# I use macchanger to randomize mac address. If without this option,
# the lease pool will burn out - NO IPs available!
release
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The example above disables &lt;em&gt;wpa_supplicant&lt;/em&gt; hook, which implies &lt;em&gt;dhcpcd&lt;/em&gt; won&apos;t launch &lt;em&gt;wpa_supplicant&lt;/em&gt; functionality.&lt;/p&gt;

&lt;h1 id=&quot;mac-spoofing&quot;&gt;MAC Spoofing&lt;/h1&gt;

&lt;p&gt;Now we do some trick on networking control. Anonymity on network is important. We can hide our IP/identity on the Internet by &lt;em&gt;Tor&lt;/em&gt;, &lt;em&gt;NAT&lt;/em&gt; etc. However that does not work within LAN due to MAC address!&lt;/p&gt;

&lt;p&gt;Though MAC address won&apos;t go out of LAN, but it&apos;s plain within that scope. Enveryone in LAN can identify you by MAC address, thus motivating MAC Spoofing. Each time, we spoof a MAC address, the DHCP servers treat it as a new joint device and asign a new IP from the pool.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Notice&lt;/em&gt;: xx:xx:xx:xx:xx means permanent address while yy:yy:yy:yy:yy:yy is fake address.&lt;/p&gt;

&lt;h2 id=&quot;manually&quot;&gt;Manually&lt;/h2&gt;

&lt;p&gt;Manually means change MAC address on command line. Pior to spoofing, we should make sure the interface id down. Basically, we resort to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;ifconfig&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ifconfig wlan0 down
ifconfig wlan0 hw ether XX:XX:XX:XX:XX:XX
ifconfig wlan0 up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Some drivers might not support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hw&lt;/code&gt; option.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;iproute2&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ip link set dev wlan0 down
ip link set dev wlan0 address XX:XX:XX:XX:XX:XX
ip link set dev wlan0 up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;macchanger&lt;/p&gt;

    &lt;p&gt;The former two are almost the same except the syntax, while &lt;em&gt;macchanger&lt;/em&gt; is smarter with fine control. &lt;em&gt;macchanger&lt;/em&gt; is a package capable of complex MAC spoofing like &lt;em&gt;reserve vendor type&lt;/em&gt;, &lt;em&gt;any vendor&lt;/em&gt;, &lt;em&gt;fully random&lt;/em&gt; etc.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;emerge -avt macchanger
emerge -avt --oneshot &amp;gt;=netifrc-0.2.3 (opt)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;macchanger&lt;/em&gt; has bumped to verion 1.7.0 which returns different string on exit. However, &lt;em&gt;&amp;lt;netifrc-0.2.3&lt;/em&gt; still examines the old exit string, error-prone. If you manage networking by OpenRC &lt;em&gt;net config&lt;/em&gt;, then bump to &lt;em&gt;&amp;gt;=netifrc-0.2.3&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ip link set dev wlan0 down
machanger -A wlan0
ip link set dev wlan0 up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Details refer to man page.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;automation&quot;&gt;Automation&lt;/h2&gt;

&lt;p&gt;We prefer autmatic spoofing on system boot without user intervence, saving much trouble. Openrc &lt;em&gt;init script&lt;/em&gt; meets the requirement. We wrap &lt;em&gt;ifconfig&lt;/em&gt;, &lt;em&gt;ip&lt;/em&gt; or &lt;em&gt;macchanger&lt;/em&gt; command in init script.&lt;/p&gt;

&lt;p&gt;We assume the networking scheme is &lt;em&gt;dhcpcd + wpa_supplicant&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Notice&lt;/em&gt;: we should test our init script, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc-service script-name stop&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc default&lt;/code&gt; (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc&lt;/code&gt;). Don&apos;t reboot - a waste of time!&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;standard init script&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/sbin/runscript
#
# Spoof wireless interface mac address on boot
# Add other interfaces if needed
#
# `macchanger&apos; supports complex syntax compared
# to `ip&apos;

ETH0_PERMANET_MAC=&quot;xx:xx:xx:xx:xx:xx&quot;
ETH0_FAKE_MAC=&quot;yy:yy:yy:yy:yy:yy&quot;

WLAN0_PERMANENT_MAC=&quot;xx:xx:xx:xx:xx:xx&quot;
WLAN0_FAKE_MAC=&quot;yy:yy:yy:yy:yy:yy&quot;

depend() {
  after udev
  before dhcpcd
}

start() {
  if [ &quot;${RC_CMD}&quot; = &quot;restart&quot; ];
  then
    ebegin &quot;Spoofing again&quot;
    eend $?
  fi

  ebegin &quot;Spoofing MAC Address&quot;

  ip link set dev eth0 down
  #ip link set dev eth0 address $ETH0_FAKE_MAC
  macchanger -A eth0
  ip link set dev eth0 up

  ip link set dev wlan0 down
  #ip link set dev wlan0 address $WLAN0_FAKE_MAC
  macchanger -A wlan0
  ip link set dev wlan0 up

  eend $?
}

stop() {
  ebegin &quot;Oops! Not a daemon and do nothing&quot;
  eend $?
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Since we specify &lt;em&gt;before dhcpcd&lt;/em&gt; in &lt;em&gt;dpend&lt;/em&gt;, the &lt;em&gt;down/up&lt;/em&gt; wrapper can be removed unless you need manually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc-service macspoofing restart&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;local init script&lt;/p&gt;

    &lt;p&gt;Similarly, MAC spoofing can be accomplished in a ordinary local script in &lt;em&gt;/etc/local.d/&lt;/em&gt;. Actually MAC spoofing is NOT a daemon service but a few shell commands. &lt;em&gt;local init script&lt;/em&gt; fits better.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;/etc/local.d/macspoofing.start&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/bin/sh

ETH0_PERMANET_MAC=&quot;xx:xx:xx:xx:xx:xx&quot;
ETH0_FAKE_MAC=&quot;yy:yy:yy:yy:yy:yy&quot;

WLAN0_PERMANENT_MAC=&quot;xx:xx:xx:xx:xx:xx&quot;
WLAN0_FAKE_MAC=&quot;yy:yy:yy:yy:yy:yy&quot;

echo &quot;Spoofing eth0 MAC Address&quot;
ip link set dev eth0 down
#ip link set dev eth0 address $ETH0_FAKE_MAC
macchanger -A eth0
ip link set dev eth0 up

echo &quot;Spoofing wlan0 MAC Address&quot;
ip link set dev wlan0 down
#ip link set dev wlan0 address $WLAN0_FAKE_MAC
macchanger -A wlan0
ip link set dev wlan0 up
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Please make sure &lt;em&gt;local&lt;/em&gt; init is added to &lt;em&gt;default&lt;/em&gt; runlevel: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc-update add local default&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;Also mark the script as executable.&lt;/li&gt;
      &lt;li&gt;Must provide the &lt;em&gt;down/up&lt;/em&gt; wrapper since we can not guarantee the interface is down when local script is executed.&lt;/li&gt;
      &lt;li&gt;We can also revoke the script by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc-service local start&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;udev init script&lt;/p&gt;

    &lt;p&gt;Udev allows to perform MAC address spoofing by creating the udev rule. Use &lt;em&gt;address&lt;/em&gt; attribute to match the permanent MAC address and change it using the &lt;em&gt;ifconfig/ip/macchanger&lt;/em&gt; command:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/udev/rules.d/75-mac-spoof.rules

ACTION==&quot;add&quot;, SUBSYSTEM==&quot;net&quot;, ATTR{address}==&quot;XX:XX:XX:XX:XX:XX&quot;, RUN+=&quot;/usr/bin/ip link set dev %k address YY:YY:YY:YY:YY:YY&quot;
or
ACTION==&quot;add&quot;, SUBSYSTEM==&quot;net&quot;, ATTR{address}==&quot;XX:XX:XX:XX:XX:XX&quot;, RUN+=&quot;/usr/bin/macchanger -A %k&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Make sure Udev is added to a init runlevel. On Gentoo, it&apos;s by default at &lt;em&gt;sysinit&lt;/em&gt; runlevel. Udev is a low level but powerful device control module, we can do more. For example, create another rule file to rename device interface.&lt;/p&gt;

    &lt;p&gt;If you&apos;d like, set Udev log to &lt;em&gt;err&lt;/em&gt; (default), &lt;em&gt;info&lt;/em&gt; or &lt;em&gt;debug&lt;/em&gt; through:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# udevadm control --log-priority=info
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Alternatively, edit &lt;em&gt;/etc/udev/udev.conf&lt;/em&gt; manually.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;net config - discusses later&lt;/p&gt;

    &lt;p&gt;Must bump to &lt;em&gt;&amp;gt;=netifrc-0.2.3&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;release&quot;&gt;Release&lt;/h2&gt;

&lt;p&gt;When requiring IP by DHCP, we MUST tell DHCP client to &lt;em&gt;release previous lease when it stops&lt;/em&gt; for IP re-use. Otherwise, eventually all available IPs are reserved by our single interface - running out of IP!&lt;/p&gt;

&lt;p&gt;How to release? If use &lt;em&gt;dhcpcd&lt;/em&gt; to serve DHCP, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;release&lt;/code&gt; option to &lt;em&gt;dhcpcd.conf&lt;/em&gt;. For traditional &lt;em&gt;net&lt;/em&gt; config, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dhcpc_eth0=&quot;release&quot;&lt;/code&gt; to &lt;em&gt;/etc/conf.d/net&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;net-config&quot;&gt;net config&lt;/h2&gt;

&lt;p&gt;The above spoofing method assumes &lt;em&gt;dhcpcd + wpa_supplicant&lt;/em&gt; networking scheme. Actually the old &lt;em&gt;net config&lt;/em&gt; now supports MAC spoofing with &lt;em&gt;macchanger&lt;/em&gt;. This is new networking scheme:&lt;/p&gt;

&lt;p&gt;Now &lt;em&gt;net config&lt;/em&gt; + DHCP + &lt;em&gt;wpa_supplicant&lt;/em&gt; new networking scheme, where DHCP functionality is served by &lt;em&gt;dhcpcd&lt;/em&gt; package.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Symbolic&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pushd /etc/init.d/
ln -sv net.lo net.wlan0
rc-update add net.wlan0 default
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;/etc/conf.d/net&lt;/em&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;## global modules preference

# iproute2 over ifconfig
# both are for static IP setting
modules=&quot;iproute2&quot;

# DHCP: over &apos;dhclient&apos; / &apos;pump&apos; / &apos;udhcpc&apos; etc.
# For dynamic IP setting
modules=&quot;dhcpcd&quot;

# Wireless: over &apos;wireless-tools&apos; etc.
# For wireless authentication
modules=&quot;wpa_supplicant&quot;


## ethernet - eth0

# modules preference
modules_eth0=&quot;dhcpcd&quot;

# null - no IP
config_eth0=&quot;null dhcp&quot;
dhcp_eth0=&quot;release&quot;

# mac spoofing
# To randomize between the same physical type of connection (e.g. fibre,
# copper, wireless) , all vendors
mac_eth0=&quot;random-anykind&quot;


## wireless - wlan0

# modules preference
modules_wlan0=&quot;wpa_supplicant&quot;

# dhcp
config_wlan0=&quot;dhcp&quot;
dhcp_wlan0=&quot;release&quot;

# mac spoofing
# To randomize between the same physical type of connection (e.g. fibre,
# copper, wireless) , all vendors
mac_wlan0=&quot;random-anykind&quot;

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

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac_wlan0=&quot;random-anykind&quot; actually revokes &lt;/code&gt;macchanger -A wlan0`.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Update &lt;em&gt;dhcpcd&lt;/em&gt; config
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Keep &lt;em&gt;dhcpcd&lt;/em&gt; at &lt;em&gt;default&lt;/em&gt; runlevel though &lt;em&gt;net config&lt;/em&gt; can launch &lt;em&gt;dhcpcd&lt;/em&gt; process automatically!&lt;/p&gt;

        &lt;p&gt;But this lanuching is not a &lt;em&gt;daemon&lt;/em&gt; but a normal &lt;em&gt;process&lt;/em&gt;. If revoked as a normal process, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc-service net.wlp3s0 restart&lt;/code&gt; won&apos;t work due to failure stop of the &lt;em&gt;dhcpcd process&lt;/em&gt;. Seriously, we rarely execute the service restart. Hence it&apos;s safely to remove from &lt;em&gt;default&lt;/em&gt; runlevel.&lt;/p&gt;

        &lt;p&gt;The key is we still ned &lt;em&gt;dhcpcd&lt;/em&gt; to serve DHCP functionality.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Disable &lt;em&gt;wpa_supplicant&lt;/em&gt; hook since &lt;em&gt;net config&lt;/em&gt; will lanuch &lt;em&gt;wpa_supplicant&lt;/em&gt; functinality automatically.&lt;/p&gt;

        &lt;p&gt;&lt;em&gt;net config&lt;/em&gt; will definitely launch &lt;em&gt;wpa_supplicant&lt;/em&gt; but &lt;em&gt;dhcpcd&lt;/em&gt; will launch &lt;em&gt;wpa_supplicant&lt;/em&gt; as well. Thus &lt;em&gt;wpa_supplicant&lt;/em&gt; is revoked twice, causing error.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Keep the &lt;em&gt;release&lt;/em&gt; option in &lt;em&gt;dhcpcd.conf&lt;/em&gt; though it&apos;s already set in &lt;em&gt;/etc/conf.d/net&lt;/em&gt;. Just in case.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;It seems that &lt;em&gt;net config&lt;/em&gt; does NOT spoof MAC address if is no connection (i.e. no wired cable), which is a preferred way.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Booting warning:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* Starting DHCP Client Daemon ...
 [ ok ]
 * Bringing up interface wlan0
 *   Changing MAC address of wlan0 ...
 [ ok ]
 *     changed to 00:08:D3:11:9F:77
 *   Starting wpa_supplicant on wlan0 ...
Successfully initialized wpa_supplicant
 [ ok ]
 *   Starting wpa_cli on wlan0 ...
 [ ok ]
 *   Backgrounding ... ...
 * WARNING: net.wlan0 has started, but is inactive
 * WARNING: netmount will start when net.wlan0 has started
 * Starting Shadowsocks ...
INFO: loading config from /etc/shadowsocks.json
started
 [ ok ]
 * WARNING: tor will start when net.wlan0 has started
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;These warnings don&apos;t affect networking. The possbile cause is: net.wlan0 needs some time to warm up (started, but not finished yet) waiting for other services depending on (&lt;em&gt;need net&lt;/em&gt;) it. We can check &lt;em&gt;netmount&lt;/em&gt; and &lt;em&gt;tor&lt;/em&gt; init scrpit and find &lt;em&gt;need net&lt;/em&gt; in the &lt;em&gt;depend&lt;/em&gt; function.&lt;/p&gt;

    &lt;p&gt;Service started but not finished might be at &lt;em&gt;scheduling&lt;/em&gt; or &lt;em&gt;inactive&lt;/em&gt; status. We can check this by stoping all networking init service and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc default; rc-status&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;More&lt;/p&gt;

    &lt;p&gt;I can set an interface down by default. For example, to let Ethernet eth0 down default, in &lt;em&gt;net config&lt;/em&gt;, we can add &lt;em&gt;config_eth0=&quot;null&quot;&lt;/em&gt;. And in &lt;em&gt;dhcpcd.conf&lt;/em&gt;, add &lt;em&gt;denyinterfaces eth0&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Notes&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;net config&lt;/em&gt; is just a script manages networking at high level. To get connected, &lt;em&gt;net config&lt;/em&gt; revokes other tools, like &lt;em&gt;ifconfig&lt;/em&gt;, &lt;em&gt;iproute2&lt;/em&gt;, &lt;em&gt;wpa_supplicant&lt;/em&gt;, DHCP client etc. &lt;em&gt;dhcpcd&lt;/em&gt; is standalone tool, with &lt;em&gt;wpa_supplicant&lt;/em&gt;, it handles all networking connection (though &lt;em&gt;dhcpcd&lt;/em&gt; can just serves DHCP). &lt;em&gt;networkmanager&lt;/em&gt; is at a more higher level with GUI.&lt;/p&gt;

    &lt;p&gt;We&apos;d better NOT mix &lt;em&gt;net config&lt;/em&gt; and &lt;em&gt;dhcpcd&lt;/em&gt;. Use either one of them.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;mac-spoofing-summary&quot;&gt;MAC Spoofing Summary&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;em&gt;Udev init script&lt;/em&gt; is the easiest method.&lt;/li&gt;
  &lt;li&gt;Just a Udev rule. No other configuration.&lt;/li&gt;
  &lt;li&gt;No need of &lt;em&gt;net config&lt;/em&gt;. Just keep original &lt;em&gt;dhcpcd + wpa_supplicant&lt;/em&gt; settings.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;refs&quot;&gt;Refs&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/MAC_address_spoofing&quot;&gt;archi wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://perot.me/mac-spoofing-what-why-how-and-something-about-coffee&quot;&gt;what why how&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://forums.gentoo.org/viewtopic-p-7737632.html&quot;&gt;gentoo forum&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;wpa_supplicant&quot;&gt;wpa_supplicant&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;wpa_supplicant&lt;/em&gt; authenticates wireless router - data link layer where wireless traffic resides. Call it &lt;em&gt;wireless authentication&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;wpa_supplicant&lt;/em&gt; does NOT authenticates ISP&apos;s Internet access - namely &lt;em&gt;network authentication&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Without ISP authentication, even connected to wireless router, still coult NOT connect to the Internet.&lt;/li&gt;
  &lt;li&gt;When subscribing to a ISP network service, you usually are given a account and password for &lt;em&gt;network authentication&lt;/em&gt;. After that, you go home setting up a wireless router for home &lt;em&gt;wireless authentication&lt;/em&gt; - a new pair of account (&lt;em&gt;ssid&lt;/em&gt;) and password.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;network authentication&lt;/em&gt; is usually done:
    &lt;ol&gt;
      &lt;li&gt;An automatic browser page poping up for ISP account name and password; Or use the ISP software.&lt;/li&gt;
      &lt;li&gt;For public WiFi, no &lt;em&gt;network authentication&lt;/em&gt; is required. In many free WiFi situations the first time you use the service no matter where you try to go you&apos;re first intercepted and sent to a browser page where you&apos;re required to &quot;login&quot; or otherwise accept the terms of service. This page does not protect you at all. It has nothing to do with security, wireless or otherwise. It&apos;s nothing more than a bit of legalese to protect the internet provider.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;psk-vs-passphrase&quot;&gt;psk VS passphrase&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;passphrase&lt;/em&gt; is what we usually called &lt;em&gt;WiFI password&lt;/em&gt;, namely a short ( around 8) characters string. It&apos;s &lt;em&gt;easy&lt;/em&gt; to remember.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;psk&lt;/em&gt; is a &lt;em&gt;wpa_supplicant&lt;/em&gt; term used to authenticate wireless router, namely a 256 characters string. It&apos;s &lt;em&gt;hard&lt;/em&gt; to remember. To get this long &lt;em&gt;psk&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# wpa_passphrase ssid passhrase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;We use &lt;em&gt;passphrase&lt;/em&gt; to generate &lt;em&gt;psk&lt;/em&gt;. The result is shown on &lt;em&gt;stdout&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;We can find &lt;em&gt;psk&lt;/em&gt; item in &lt;em&gt;wpa_supplicant.conf&lt;/em&gt;. However, this &lt;em&gt;psk&lt;/em&gt; is a little different from the above one. &lt;em&gt;psk&lt;/em&gt; in &lt;em&gt;wpa_supplicant.conf&lt;/em&gt; can be either:
    &lt;ol&gt;
      &lt;li&gt;Short &lt;em&gt;passphrase&lt;/em&gt; with quotes;&lt;/li&gt;
      &lt;li&gt;Long &lt;em&gt;psk&lt;/em&gt; without quotes.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
  &lt;li&gt;In spite of editing &lt;em&gt;wpa_supplicant.conf&lt;/em&gt; manually, we can actually use &lt;em&gt;wpa_cli&lt;/em&gt; to configure WiFi and optionally save to &lt;em&gt;wpa_supplicant.conf&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Before running &lt;em&gt;wpa_cli&lt;/em&gt;, &lt;em&gt;wpa_supplicant&lt;/em&gt; must be started! Either by system networking init script or manually starting. If manually:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# wpa_supplicant -i wlp3s0 -D nl80211 -c /etc/wpa_supplicant/wpa_supplicant.conf -B -dd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-B&lt;/code&gt; puts &lt;em&gt;wpa_supplicant&lt;/em&gt; to the background as a daemon.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;wpa_supplicant.conf&lt;/em&gt; should at least include a line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctrl_interface=DIR=/var/run/wpa_supplicant&lt;/code&gt;. If we will save connected WiFi, then add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update_config=1&lt;/code&gt; which is not recommended for security.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;At this point, run&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# wpa_cli	# entering *wpa\_cli* interactive mode

&amp;gt; scan
OK
&amp;lt;3&amp;gt;CTRL-EVENT-SCAN-RESULTS

&amp;gt; scan_results
bssid / frequency / signal level / flags / ssid
00:00:00:00:00:00 2462 -49 [WPA2-PSK-CCMP][ESS] MYSSID
11:11:11:11:11:11 2437 -64 [WPA2-PSK-CCMP][ESS] ANOTHERSSID

&amp;gt; add_network
7
&amp;gt; set_network 7 ssid &quot;ssid&quot;
&amp;gt; set_network 7 psk &quot;passphrase&quot;
&amp;gt; enable_network 7
&amp;lt;3&amp;gt;CTRL-EVENT-CONNECTED - Connection to 00:00:00:00:00:00 completed (reauth) [id=7 id_str=]

&amp;gt;select_network 7       # optionally if the new added network is not associated with AP
   
&amp;gt;save_config		   # optionally if turned on &apos;update_config=1&apos;
OK

&amp;gt;quit

# dhcpcd wlan0	# optionally if NO DHCP client client is running on the interface
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;You can see just &lt;em&gt;scan scan_results add_network set_network enable_network&lt;/em&gt; is OK. The network has a number (0 above) specifying how many networks has been configured in &lt;em&gt;wpa_supplicant.conf&lt;/em&gt;. This number increases sequencially.&lt;/li&gt;
      &lt;li&gt;If the SSID does not have password authentication (i.e. public WiFi), you must explicitly configure the network as keyless by replacing the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set_network 0 psk &quot;passphrase&quot;&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set_network 0 key_mgmt NONE&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;At the point of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;save_config&lt;/code&gt;, a &lt;em&gt;wireless authentication&lt;/em&gt; is established. To surf the Internet, we need IP and &lt;em&gt;network authentication&lt;/em&gt;.
        &lt;ol&gt;
          &lt;li&gt;To get IP, usually just run a DHCP client. If there is not a DHCP client running on the interface, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dhcpcd wlan0&lt;/code&gt;. &lt;em&gt;Attention&lt;/em&gt;: this will only letting DHCP client running on the specified interface &lt;em&gt;wlan0&lt;/em&gt;, neglecting others.&lt;/li&gt;
          &lt;li&gt;Network authentication, discussed above.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;refs-1&quot;&gt;Refs&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Wpa_supplicant#Connecting_with_wpa_cli&quot;&gt;arch wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/buhman/7162560&quot;&gt;gists&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;other-functionality&quot;&gt;Other functionality&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Proxy&lt;/li&gt;
  &lt;li&gt;Tor&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;refs-2&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Handbook:AMD64/Full/Networking&quot;&gt;gentoo wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Init script</title>
   <link href="/2016/03/01/init-script/"/>
   <updated>2016-03-01T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/03/01/init-script</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;Most daemon (service) brings along init script on installation, like LVM, Tor, Dhcpcd etc.&lt;/li&gt;
  &lt;li&gt;User defines their own daemon. In this post, I show procedures to generate a Gentoo init script of &lt;em&gt;ss&lt;/em&gt; proxy. Make sure it&apos;s started on boot.&lt;/li&gt;
  &lt;li&gt;There are two methods to add personal init script.
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Write a init script directly (&lt;em&gt;/etc/init.d/&lt;/em&gt;).&lt;/p&gt;

        &lt;p&gt;Init script is mainly for &lt;em&gt;daemon&lt;/em&gt; in the background.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Write a simple script (&lt;em&gt;/etc/local.d/&lt;/em&gt;) revoked by a special init script &lt;em&gt;local&lt;/em&gt; (&lt;em&gt;/etc/init.d/local&lt;/em&gt;). Of course, we make sure &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc-update add local default&lt;/code&gt;.&lt;/p&gt;

        &lt;p&gt;Local script focuses on simple foreground script that executes only once. For example, write a value to a file on boot.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Handbook:X86/Working/Initscripts&quot;&gt;wiki initscript&lt;/a&gt; and &lt;a href=&quot;https://wiki.gentoo.org/wiki//etc/local.d&quot;&gt;local.d&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/sbin/runscript&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# To launch shadowsocks proxy at default runlevel&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# https://wiki.gentoo.org/wiki/Handbook:AMD64/Working/Initscripts&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Tor uses Shadowsocks as frontend proxy. So launch&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# it &apos;before tor&apos;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Put $DAEMON arguments after two succesive dashes &apos;--&apos;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &apos;sslocal&apos; create $PIDFILE by default. We just tell&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &apos;start-stop-daemon&apos; the location by &apos;--pidfile&apos;.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# &apos;start-stop-daemon&apos; arguments resides before &apos;--exec&apos;.&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;DAEMON&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/usr/bin/sslocal&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PIDFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/var/run/shadowsocks.pid&quot;&lt;/span&gt;

depend&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  before tor
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

start&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;DAEMON_OPTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-c /etc/shadowsocks.json -q -d start --log-file /var/log/shadowsocks.log&quot;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;RC_CMD&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;restart&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;ebegin &lt;span class=&quot;s2&quot;&gt;&quot;Restarting&quot;&lt;/span&gt;
    eend &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;fi
  
  &lt;/span&gt;ebegin &lt;span class=&quot;s2&quot;&gt;&quot;Starting Shadowsocks&quot;&lt;/span&gt;
  start-stop-daemon &lt;span class=&quot;nt&quot;&gt;--start&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--pidfile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PIDFILE&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--exec&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$DAEMON&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$DAEMON_OPTS&lt;/span&gt;
  eend &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

stop&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  ebegin &lt;span class=&quot;s2&quot;&gt;&quot;Stopping Shadowsocks&quot;&lt;/span&gt;
  start-stop-daemon &lt;span class=&quot;nt&quot;&gt;--stop&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--pidfile&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$PIDFILE&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--exec&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$DAEMON&lt;/span&gt;
  eend &lt;span class=&quot;nv&quot;&gt;$?&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Tor - Anonymity Online</title>
   <link href="/2016/02/28/tor/"/>
   <updated>2016-02-28T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/02/28/tor</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;All ip[6]tables commands now should be converted into &lt;em&gt;/var/lib/ip[6]tables/rules-save&lt;/em&gt; and use &lt;em&gt;ip[6]tables-apply&lt;/em&gt; instead. Refer to post &lt;em&gt;iptables&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Tor - the onion router - mainly devotes to hide your Internet identity.&lt;/li&gt;
  &lt;li&gt;Tor prevents people from learning your location or browsing habits.&lt;/li&gt;
  &lt;li&gt;Tor is for web browsers, instant messaging clients, and more.&lt;/li&gt;
  &lt;li&gt;Tor aims at outbound traffic.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;how&quot;&gt;How&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Tor periodically chooes different encryption routing relays. Exit relay&apos;s IP is your Tor IP.&lt;/li&gt;
  &lt;li&gt;Tor needs a centralized &lt;em&gt;directory host&lt;/em&gt; to receve a list of relays on which Tor builds Tor circuit/route.&lt;/li&gt;
  &lt;li&gt;Tor traffic is NOT encrypted between &lt;em&gt;exit relay&lt;/em&gt; and destination host. But that does not impact anonymoity online.&lt;/li&gt;
  &lt;li&gt;Tor is blocked:
    &lt;ol&gt;
      &lt;li&gt;Block the &lt;em&gt;directory host&lt;/em&gt;;&lt;/li&gt;
      &lt;li&gt;Block the &lt;em&gt;handshake&lt;/em&gt; process by itself fingerprints of Tor traffic between Tor client and the entry relay;&lt;/li&gt;
      &lt;li&gt;Block intermediate relys;&lt;/li&gt;
      &lt;li&gt;Malicious relays (honey pots).&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;To solve the issue:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Front end proxy;&lt;/li&gt;
      &lt;li&gt;Tor Bridge;&lt;/li&gt;
      &lt;li&gt;Tor Bridge and PT (Pluggable Transports) protocol.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add a frontend proxy (Lantern for instance) to Tor. Frontend proxy bypasses censorship while Tor hide your Internet track. The frontend proxy must support SOCKS protocol by itself. GAE does NOT support SOCKS itself, so cannot be a frontend proxy.&lt;/p&gt;

    &lt;p&gt;In this post, I use &lt;em&gt;ss&lt;/em&gt; (also a SOCKS5) as the frontend proxy.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;On startup, Tor access the &lt;em&gt;directory host&lt;/em&gt; to get a list of relays. But the replays there are public to everyone, prone to blocking. By specifing private relay - &lt;em&gt;Bridges&lt;/em&gt; in configuration file, Tor build circuits based on them.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;Do NOT enable Front end proxy and Bridges simutaneously&lt;/em&gt;, otherwise Tor would not work!&lt;/p&gt;

    &lt;p&gt;Mostly, I use Frontend proxy: mutliple proxies more secure. But for public Wi-Fi, we&apos;d better use Bridges.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Sometimes Bridge is not enough to circumvent traffic censorship. Traffic between Tor client and the entry relay can be peeked and analyzed even the palyload is encrypted.&lt;/p&gt;

    &lt;p&gt;On such case, we need Bridges with &lt;em&gt;pluggable transports&lt;/em&gt; support. &lt;em&gt;pluggable transports&lt;/em&gt; obfuscate traffic between Tor client and the entry relay. Disguise the Tor traffic as normal.&lt;/p&gt;

    &lt;p&gt;It does NOT make any sense to run PT alone. It should be &lt;em&gt;managed&lt;/em&gt; by applications that require TCP obfuscation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Use Tor not only to surf the Internet, but for other applications that support SOCKS5.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;net-misc/tor transparent-proxy&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge net-misc/tor&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-service tor start&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-update add tor default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;configuration---etctortorrc&quot;&gt;Configuration - &lt;em&gt;/etc/tor/torrc&lt;/em&gt;&lt;/h1&gt;

&lt;p&gt;Refer to &lt;em&gt;/etc/tor/torrc.sample&lt;/em&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man tor&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Basics&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;User tor
PIDFile /var/run/tor/tor.pid
Log notice syslog
DataDirectory /var/lib/tor/data
AvoidDiskWrites 1
DirReqStatistics 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Frontend proxy&lt;/p&gt;

    &lt;p&gt;Tor is blocked by GFW. We add a frontend proxy to Tor bypassing GFW. This proxy server will be inserted between &lt;em&gt;localhost&lt;/em&gt; and Tor &lt;em&gt;entry relay&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;This post uses &lt;em&gt;ss&lt;/em&gt; - a SOCKS5 proxy.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Socks5Proxy 127.0.0.1:1080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Application -&amp;gt; Tor -&amp;gt; frontend proxy -&amp;gt; entry relay -&amp;gt; intermediate rely -&amp;gt; exit relay -&amp;gt; destination host.&lt;/p&gt;

    &lt;p&gt;Traffic between application and exit relay is encrypted. Localhost IP is plain between application and frontend proxy.&lt;/p&gt;

    &lt;p&gt;Though frontend proxy knows your IP but the traffic is encrypted! Exit relays and destination host know your traffic but does not know your real IP. What&apos;s more, if you visit destination host by &lt;em&gt;https&lt;/em&gt;, then exit relay only knows encrypted &lt;em&gt;https&lt;/em&gt; traffic.&lt;/p&gt;

    &lt;p&gt;Bingo!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Bridges with PT&lt;/p&gt;

    &lt;p&gt;Without PT protocol:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;local app -&amp;gt; local Tor client -&amp;gt; Bridges Tor client/server -&amp;gt; destitionation site&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;With PT protocol:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;local app -&amp;gt; local Tor client -&amp;gt; local PT protocol client -&amp;gt; Brdiges PT protocol server -&amp;gt; Bridges Tor server -&amp;gt; destitionation host&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;There are different pluggable transports, namely &lt;em&gt;obfs1/2/3&lt;/em&gt;, &lt;em&gt;scramblesuit&lt;/em&gt;, &lt;em&gt;meek&lt;/em&gt;, &lt;em&gt;obfs4&lt;/em&gt; etc. Currently, &lt;em&gt;obfs4&lt;/em&gt; is best and next comes &lt;em&gt;meek&lt;/em&gt; while the others can be blocked as well. &lt;a href=&quot;https://bridges.torproject.org/&quot;&gt;get bridges&lt;/a&gt; tells how to obtain bridge address (usually 3 is enough).&lt;/p&gt;

    &lt;p&gt;To use pluggable transports, we should install the client first. The server is running at Bridges. Package &lt;em&gt;net-proxy/obfsproxy&lt;/em&gt; (written with Python) supports &lt;em&gt;managed&lt;/em&gt;, &lt;em&gt;obfs2&lt;/em&gt;, &lt;em&gt;dummy&lt;/em&gt;, &lt;em&gt;obfs3&lt;/em&gt;, &lt;em&gt;scramblesuit&lt;/em&gt;, &lt;em&gt;b64&lt;/em&gt;. Unfortunately, it does not support &lt;em&gt;obfs4&lt;/em&gt; or &lt;em&gt;meek&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;We need &lt;em&gt;&lt;a href=&quot;https://github.com/Yawning/obfs4.git&quot;&gt;obfs4proxy&lt;/a&gt;&lt;/em&gt; that implements the obfuscation protocols &lt;em&gt;obfs2&lt;/em&gt;, &lt;em&gt;obfs3&lt;/em&gt;, &lt;em&gt;scrambleSuit&lt;/em&gt; (client only), &lt;em&gt;meek&lt;/em&gt; (client only) and &lt;em&gt;obfs4&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;There is no ebuild available. I have written one in local overlay. But there are simpler way. Unlike Python script &lt;em&gt;net-proxy/obfsproxy&lt;/em&gt;, &lt;em&gt;obfs4proxy&lt;/em&gt; is just a binary executable. We can 1) copy the binary from official Tor browser (&lt;em&gt;tor-browser_en-US/Browser/TorBrowser/Tor/PluggableTransports/&lt;/em&gt;); 2) build one manually.&lt;/p&gt;

    &lt;p&gt;Manually compilation is easy! &lt;em&gt;obfs4proxy&lt;/em&gt; is written by Go language. From &lt;a href=&quot;https://gitweb.torproject.org/pluggable-transports/obfs4.git/tree/README.md&quot;&gt;README&lt;/a&gt;, there are 6 build-time dedpencies. Only &lt;em&gt;dev-lang/go&lt;/em&gt; should be installed while the other 5 will be cloned (by &lt;em&gt;dev-vcs/git&lt;/em&gt;) automatically on the fly. We can compile in a normal user account.&lt;/p&gt;

    &lt;p&gt;The local compile process won&apos;t impact portage system as long as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GOPATH&lt;/code&gt; is confined to somewhere like &lt;em&gt;~/workspace/go&lt;/em&gt;. Everything goes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GOPATH&lt;/code&gt; during the whole compiling process.&lt;/p&gt;

    &lt;p&gt;Generally, three directories will created under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GOPATH&lt;/code&gt;, namely &lt;em&gt;${GOPATH}/src&lt;/em&gt; (downloaded source code), &lt;em&gt;${GOPATH}/bin&lt;/em&gt; (binary &lt;em&gt;obfs4proxy&lt;/em&gt;), &lt;em&gt;${GOPATH}/pkg&lt;/em&gt; (build-time Go pkgs). Finally &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp $GOPATH/bin/obfs4proxy /usr/local/bin&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;The 6 dependencies are all built-time ones. &lt;em&gt;dev-lang/go&lt;/em&gt; will be removed on next &lt;em&gt;emerge –depclean&lt;/em&gt;. For the other 5, remove &lt;em&gt;${GOPATH}/src&lt;/em&gt; and &lt;em&gt;${GOPATH}/pkg&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt [--oneshot] dev-lang/go&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOPATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/workspace/obfs4proxy
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;go &lt;span class=&quot;nb&quot;&gt;help &lt;/span&gt;get/install/build
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;go get &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-work&lt;/span&gt; git.torproject.org/pluggable-transports/obfs4.git/obfs4proxy
&lt;span class=&quot;c&quot;&gt;# copy $GOPATH/bin/obfs4proxy /usr/local/bin&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# chmod +x /usr/local/bin/obfs4proxy&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# obfs4proxy --version&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avc dev-lang/go&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$GOPATH&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;unset &lt;/span&gt;GOPATH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;That&apos;s all. An interesting notice: the Github/Gitweb repository name is &lt;em&gt;obfs4&lt;/em&gt; but the finally binary is &lt;em&gt;obfs4proxy&lt;/em&gt;. Also the compiling entry point is also &lt;em&gt;obfs4.git/obfs4proxy&lt;/em&gt; which will depend on others like &lt;em&gt;obfs4.git/transports&lt;/em&gt; etc. &lt;em&gt;obfs4&lt;/em&gt; repository implements different pluggable transports and output binary &lt;em&gt;obfs4proxy&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Now update Tor config:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;UseBridges 1
Bridge obfs3 ...
Bridge scramblesuit ...
Bridge obfs4 ...
ClientTransportPlugin obfs3,scramblesuit, obfs4 exec /usr/local/bin/obfs4proxy --enableLogging
UpdateBridgesFromAuthority 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Test bridges speed on &lt;a href=&quot;https://atlas.torproject.org&quot;&gt;Atlas&lt;/a&gt;. Finally send &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HUP&lt;/code&gt; singal to Tor service &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;killall -s HUP tor&lt;/code&gt;!&lt;/p&gt;

    &lt;p&gt;If Atlas fails to find the bridges, congratulations, this is a brand new bridge and unlikely censorsed.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Actually by some special configuration, obfs4proxy can be used to obfuscate any other TCP traffic&lt;/em&gt;. Refer to &lt;a href=&quot;https://github.com/gumblex/ptproxy&quot;&gt;ptproxy&lt;/a&gt; and &lt;a href=&quot;https://typeblog.net/obfourscating-shadowsocks-with-obfs4/&quot;&gt;你混淆了&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Ref&lt;/em&gt;:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;https://gitlab.com/kpanic/kpanic-overlay-mirror/blob/master/net-misc/meek/meek-9999.ebuild&quot;&gt;meek ebuid&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://trac.torproject.org/projects/tor/wiki/doc/meek&quot;&gt;meek doc&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/PeterCxy/gentoo-peter/blob/master/net-proxy/obfs4proxy/obfs4proxy-9999.ebuild&quot;&gt;obfs4proxy ebuild&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://gitweb.torproject.org/pluggable-transports/obfs4.git/&quot;&gt;obfs4proxy doc&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Stream isolation&lt;/p&gt;

    &lt;p&gt;Isolate different applications by Tor port. By default, Tor service listens on &lt;em&gt;9050&lt;/em&gt; port for all traffic. We can open more Tor ports for different applications.&lt;/p&gt;

    &lt;p&gt;For example, web browser and instant messanger should better connect to Tor ports.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# web browser
SocksPort 127.0.0.1:9050
# gpg client
SocksPort 127.0.0.1:9100
# instant messenger
SocksPort 127.0.0.1:9150
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;ExcludeNodes&lt;/p&gt;

    &lt;p&gt;Tor relies on routing &lt;em&gt;relay&lt;/em&gt;. There are also malicious relays set by attacker/countries to analyze Tor traffic.&lt;/p&gt;

    &lt;p&gt;Tell Tor not to use those relays:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ExcludeNodes {cn},{hk},{mo}
strictnodes 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Others are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kp ir sy pk cu vn&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;TorDNS&lt;/p&gt;

    &lt;p&gt;Though &lt;em&gt;Tor + frontend proxy&lt;/em&gt; is secure enough to hide your surfing track, DNS server still knows where you connect. So we further hide the DNS resolving process.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;ATTENTION&lt;/em&gt;: even you choose not to use Tor surfing the Internet, you can always use TorDNS resolver. That is why I add &lt;em&gt;tor&lt;/em&gt; to default run level.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Turn on TorDNS&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;DNSPort 9053
DNSListenAddress 127.0.0.1
VirtualAddrNetworkIPv4 10.192.0.0/10
AutomapHostsOnResolve 1
AutomapHostsSuffixes .exit,.onion
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;The 3rd line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VirtualAddrNetworkIPv4 10.192.0.0/10&lt;/code&gt; is very important! Otherwise, some applications cannot resolve (TorDNS) or connect to (Transparent proxy discussed below) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.onion .exit&lt;/code&gt; address.&lt;/p&gt;

        &lt;p&gt;Now TorDNS is listening at port 9053 as a DNS server. We can make use of &lt;em&gt;tor-resolve&lt;/em&gt; to query DNS.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;TorDNS command line tool.&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tor-resolve www.baidu.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;It is possible to configure your system, if so desired, to use TorDNS for &lt;em&gt;all&lt;/em&gt; queries your system makes, regardless of whether or not you eventually use Tor to connect to your final destination.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;[optinal] Change &lt;em&gt;nameserver&lt;/em&gt;&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/resolv.conf
nameserver 127.0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;ol&gt;
          &lt;li&gt;If &lt;em&gt;DNSListenAddress&lt;/em&gt; is set to &lt;em&gt;0.0.0.0&lt;/em&gt;, then any host IP (including &lt;em&gt;127.0.0.1&lt;/em&gt;) is OK.&lt;/li&gt;
          &lt;li&gt;This step is optional due to the REDIRECT/DNAT rule in the next step.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Redirect DNS request to &lt;em&gt;DNSPort&lt;/em&gt;&lt;/p&gt;

        &lt;p&gt;By default, DNS resolving goes to port 53. DNS queries will go to &lt;em&gt;127.0.0.1:53&lt;/em&gt; instead of &lt;em&gt;DNSPort 9053&lt;/em&gt;. So need to &lt;em&gt;redirect&lt;/em&gt; DNS queries from port 53 to 9053.&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# iptables -t nat -A OUTPUT -p TCP --dport 53 -j REDIRECT --to-ports 9053&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# iptables -t nat -A OUTPUT -p UDP --dport 53 -j DNAT --to-destination 127.0.0.1:9053&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;&lt;strong&gt;A far better solution is setting &lt;em&gt;DNSPort 53&lt;/em&gt; and such no REDIRECT needed&lt;/strong&gt;. Binding to low ports (53 less than 1024) need &lt;em&gt;root&lt;/em&gt; privilege. If you send HUP signal to Tor daemone, it crashes.&lt;/p&gt;

        &lt;p&gt;On system startup (OpenRC init script) or daemon restart (&lt;em&gt;rc-service&lt;/em&gt;), Tor is ran as &lt;em&gt;root&lt;/em&gt; and binding to low port 53 is fine. After start, Tor downgrades to &lt;em&gt;tor&lt;/em&gt; account and drop &lt;em&gt;root&lt;/em&gt; privileges. You can check this by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ps -ef | grep -i tor&lt;/code&gt;. A &lt;em&gt;tor&lt;/em&gt; user account is created after package installation. So Tor does not need to run as &lt;em&gt;root&lt;/em&gt;.&lt;/p&gt;

        &lt;p&gt;After dropping the privileges, reloading config will try to bind to low port 53 again. But this time, Tor crashes due permission. So if binding to low port, we can only restart Tor as &lt;em&gt;root&lt;/em&gt; instead of HUP signal.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Disable Dhcpcd&apos;s &lt;em&gt;resolve.conf&lt;/em&gt; hook, otherwise it will override &lt;em&gt;/etc/resolv.conf&lt;/em&gt; file on startup.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/dhcpcd.conf
nohook resolv.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;Another obvious method is to remove &lt;em&gt;/lib/dhcpcd/dhcpcd-hooks/20-resolv.conf&lt;/em&gt; file.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Now all DNS request on system will use TorDNS.&lt;/p&gt;

        &lt;p&gt;Try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ping www.google.com&lt;/code&gt;&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;torify - command line tool&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;torify&lt;/em&gt; will allow application traffic flows via the Tor network without any extra application configuration changes. To use &lt;em&gt;torify&lt;/em&gt;, there must be a underlying SOCKS wrapper, i.e. &lt;em&gt;tsocks&lt;/em&gt; (almost dead), &lt;em&gt;torsocks&lt;/em&gt; etc.&lt;/p&gt;

    &lt;p&gt;Force traffic through Tor on demand in terminal, i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ usewithtor emacs&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ torsocks emacs&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ torify emacs&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;Application like Firefox configures their proxy settings to use Tor proxy. But it&apos;s annoying to configure each application to use Tor. What&apos;s worse, some application even does NOT allow proxy like Bitorrent, wget, apt-get, gpg, etc.&lt;/p&gt;

    &lt;p&gt;This is where torify plays a role: &lt;em&gt;force&lt;/em&gt; applications to use proxy. Applications utilize Tor transparently.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -av net-proxy/torsocks&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;torify wget &lt;span class=&quot;nt&quot;&gt;-qO-&lt;/span&gt; https://check.torproject.org/ | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; congratulations
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget &lt;span class=&quot;nt&quot;&gt;-qO-&lt;/span&gt; https://check.torproject.org/ | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; congratulations
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;It calls &lt;em&gt;torsocks&lt;/em&gt; wrapper with a tor specific configuration file (&lt;em&gt;/etc/torsocks.conf&lt;/em&gt;). Compare the output between &lt;em&gt;torify&lt;/em&gt; and without &lt;em&gt;torify&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Refer to &lt;a href=&quot;https://trac.torproject.org/projects/tor/wiki/doc/TorifyHOWTO&quot;&gt;torify howto&lt;/a&gt; and  &lt;a href=&quot;https://trac.torproject.org/projects/tor/wiki/doc/torsocks&quot;&gt;torsocks&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;torsocks - more&lt;/p&gt;

    &lt;p&gt;In previous step, &lt;em&gt;torify&lt;/em&gt; make use of &lt;em&gt;torsocks&lt;/em&gt; to force application traffic through Tor SOCKS5. &lt;em&gt;torify&lt;/em&gt; calls &lt;em&gt;torsocks&lt;/em&gt; with the default configuration file &lt;em&gt;/etc/torsocks.conf&lt;/em&gt; in which the default port is 9050 - Tor&apos;s default SocksPort! There are other arguments like server address, socks type etc.&lt;/p&gt;

    &lt;p&gt;To use torsocks directly, just replace &lt;em&gt;torify&lt;/em&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usewithtor&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;torsocks&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ usewithtor wget -qO- https://check.torproject.org/ | grep -i congratulations&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;It seems that &lt;em&gt;torsocks&lt;/em&gt; only supports Tor SOCKS. If I change &lt;em&gt;/etc/torsocks.conf&lt;/em&gt; to use Shadowsocks, it does not work.&lt;/p&gt;

    &lt;p&gt;It&apos;s recommended to use &lt;strong&gt;proxychains&lt;/strong&gt; instead.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Transparent proxy&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;configuration might be DEPCRECATED, please refer to lastest config file&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Though &lt;em&gt;torify&lt;/em&gt; and &lt;em&gt;torsocks&lt;/em&gt; force traffic through Tor netowrk without bothering configurating applications, they can only executed on command line. With transparent proxy setting, all non-Tor owned traffic will be redirected to Tor&apos;s &lt;em&gt;TransPort&lt;/em&gt; with command line interfence or application configuration.&lt;/p&gt;

    &lt;p&gt;Tor alone cannot achieve transparent proxy without support from Linux kernel&apos;s &lt;em&gt;netfilter&lt;/em&gt; functionality which is the core of Link firewall - Iptables.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;SocksPort&lt;/em&gt; and &lt;em&gt;DNSPort&lt;/em&gt; are Tor owned traffic. The former is Tor&apos;s TCP traffic while the later is a special case - UDP traffic. Now Iptables will redirect all non-Tor traffic to &lt;em&gt;TransPort&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Once in place, applications do not need to be configured to use Tor, though Tor&apos;s &lt;em&gt;SocksPort&lt;/em&gt; will still work. This also works for DNS via Tor&apos;s &lt;em&gt;DNSPort&lt;/em&gt;, but realize that Tor only supports TCP, thus UDP packets other than DNS cannot be sent through Tor and therefore must be blocked entirely to prevent leaks. Using iptables to transparently torify a system affords comparatively strong leak protection.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Enable Tor&apos;s transparent proxy functionality.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;TransPort 9040
TransListenAddress 127.0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NETFILTER_ADVANCED&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XT_MATCH_OWNER&lt;/code&gt; kernel option first.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;advanced netfiler configuration netfilter_advanced
  &amp;lt;*&amp;gt;   &quot;owner&quot; match support xt_match_owner
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;Without these two kernel support, iptables won&apos;t recognize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-m owner&lt;/code&gt; match.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Redirect non-Tor traffic to transparent proxy&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner tor -j DNAT --to-destination 127.0.0.1:9040&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-service iptables save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;After the setting, all traffic is owned by Tor.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Pay attention to:
        &lt;ol&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p tcp&lt;/code&gt; must accompany &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dport&lt;/code&gt; since only TCP layer has a port number.&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p tcp&lt;/code&gt; actually implied implicit arguments &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-m tcp&lt;/code&gt; which is followed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--dport&lt;/code&gt;.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Turn off Foxyproxy of Firefox, since no longer needed!&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;coarse-grained&lt;/strong&gt;: all non-Tor traffic goes through Tor now.&lt;/p&gt;

        &lt;p&gt;A fine-grained setting is turn on transparent proxy, use user-defined chain to control in detail which concrete outgoing traffic uses transparent proxy on demand. More on transparent proxy, refer to post &lt;em&gt;iptables&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Disable non-Tor traffic - an alternative.&lt;/p&gt;

    &lt;p&gt;Another extreme way is to disable non-Tor traffic completely.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# iptables -P OUTPUT DROP&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# iptables -A OUTPUT -i lo -j ACCEPT&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# iptables -A OUTPUT -m owner --uid-owner tor -j ACCEPT&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# iptables -P INPUT DROP&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# iptables -I INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# iptables -I INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Choose one of the three shceme on security requirement. In daily usage, &lt;em&gt;torify&lt;/em&gt; and/or &lt;em&gt;torsocks&lt;/em&gt; suffices.&lt;/li&gt;
  &lt;li&gt;Restart Tor service&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   # rc-service tor restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;firefox-setting&quot;&gt;Firefox setting&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The main usage of Tor resides in &lt;em&gt;WWW surfing&lt;/em&gt;. First make sure &lt;em&gt;foxproxy&lt;/em&gt; extension is installed.&lt;/p&gt;

    &lt;p&gt;I have configured &lt;em&gt;foxproxy&lt;/em&gt; for &lt;em&gt;ss&lt;/em&gt; previously.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In &lt;em&gt;foxproxy&lt;/em&gt;, &lt;em&gt;Add New Proxy&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Proxy Name: tor-ss
  Perform remote DNS lookups on hostnames ...

Host or IP Address: 127.0.0.1 Port: 9050
SOCKS proxy SOCKS v5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Remember to place the Tor proxy at the beggining of proxy list - highest proxy priority!&lt;/li&gt;
      &lt;li&gt;Now Firefox has two proxies to choose from.&lt;/li&gt;
      &lt;li&gt;Tick &lt;em&gt;Perform remote DNS lookups …&lt;/em&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;about:config&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;network.proxy.socks_remote_dns    true
network.dns.disablePrefetch       true
network.dns.disableIPv6           true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This way Firefox will resolve host names via Tor proxy DNS resolver (i.e. &lt;em&gt;ss&lt;/em&gt; also support DNS resolving. Talked laster), which prevents DNS leaks.&lt;/p&gt;

    &lt;p&gt;The first item is the key to use TorDNS.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;usage&quot;&gt;Usage&lt;/h1&gt;

&lt;h2 id=&quot;prerequisite&quot;&gt;Prerequisite&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;As we add a frontend proxy to Tor, it should launch before Tor working.&lt;/li&gt;
  &lt;li&gt;All DNS lookups on system are through Tor. If application failed to resolve hostnames, check if Tor is running.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;applications&quot;&gt;Applications.&lt;/h2&gt;

&lt;p&gt;Any applications that support SOCKS5 proxy can make use of Tor service.&lt;/p&gt;

&lt;p&gt;In its proxy setting, fill &lt;em&gt;socks5&lt;/em&gt; server to &lt;em&gt;127.0.0.1&lt;/em&gt; and &lt;em&gt;port&lt;/em&gt; to one of the &lt;em&gt;stream isolation&lt;/em&gt; port number.&lt;/p&gt;

&lt;p&gt;For those do NOT support proxy or Tor, refer to &lt;em&gt;transparent proxy&lt;/em&gt; above.&lt;/p&gt;

&lt;h2 id=&quot;firefox&quot;&gt;Firefox&lt;/h2&gt;

&lt;p&gt;Up to now, Firefox has two SOCKS5 proxy servers Tor and &lt;em&gt;ss&lt;/em&gt; to choose from. You can choose either one or both simultaneously through &lt;em&gt;foxproxy&lt;/em&gt; extension.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;ss&lt;/em&gt; for all URLs&lt;/p&gt;

    &lt;p&gt;Use &lt;em&gt;ss&lt;/em&gt; proxy surfing the Internet.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Tor alone&lt;/p&gt;

    &lt;p&gt;Use Tor surfing the Internet. However, Tor is blocked by GFW making this method infeasible.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Simutaneously&lt;/p&gt;

    &lt;p&gt;That&apos;s how Tor is commonly used: support from frontend proxy. Recall that we add &lt;em&gt;SocksProxy&lt;/em&gt; in Tor&apos;s configuration to enable &lt;em&gt;ss&lt;/em&gt; frontend proxy.&lt;/p&gt;

    &lt;p&gt;When choosing &lt;em&gt;tor for all URLs&lt;/em&gt; in &lt;em&gt;foxproxy&lt;/em&gt;, Firefox actually use Tor + &lt;em&gt;ss&lt;/em&gt; concurrently.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Of course, we can choose &lt;em&gt;use proxies based on their pre-defined patterns and priorities&lt;/em&gt; in &lt;em&gt;foxproxy&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The popular &lt;em&gt;wget&lt;/em&gt; utility cannot talk to socks proxy. However, you can use the tor network to download any resource located at a given URL and save it in a FILE using &lt;em&gt;curl&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--socks5-hostname&lt;/span&gt; 127.0.0.1:9050 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; FILE URL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;dns-resolving&quot;&gt;DNS resolving&lt;/h2&gt;

&lt;p&gt;As discussed above, the system is configured to use TorDNS resolver preventing DNS lookup leaks. All DNS requests are &lt;em&gt;redirecting&lt;/em&gt; to TorDNS by &lt;em&gt;iptables&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Try to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc-service tor stop&lt;/code&gt;, then the system cannot resolve DNS anymore as TorDNS is down!&lt;/p&gt;

&lt;h1 id=&quot;tips&quot;&gt;Tips&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Don&apos;t use Tor to sign in Email/forum. The purpose of Tor is hiding traffic tack. Email, forum etc systems can analyze your traffic. No matter which method you use for connection, final interaction with sign in system is plain text.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;关于深网&lt;/p&gt;

    &lt;p&gt;深网用户通过特殊的技术手段隐匿用户信息（如IP地址等）登陆“深网”以后，就能完全脱离世间法律或NSA（美国国家安全局）等政府管制力量的钳制和监管，在那里，你可以通过网站肆意的购买枪支弹药，可以发布悬赏杀人的告示，可以购买冰毒和可卡因，可以随意浏览儿童色情网站，也可以办理各种假证伪造身份。仅有4%的网络数据是可以通过搜索引擎找到的，其他的都深藏在“深网”中。&lt;/p&gt;

    &lt;p&gt;96%的网络数据都是无法用使用搜索引擎查找的，但这些网站的服务器实体可能分布在互联网管制薄弱的东欧国家，背后由深谙网络安全技术的黑客维护，多以.onion作为域名，采用特殊的加密机制，不能通过搜索引擎查找，即使知道域名也无法采用传统的HTTP方式直接访问，必须采用特殊手段才能接入，就好像只有游吟诗人维吉尔的引领，但丁才可以窥见Limbo里的曲径通幽处。&lt;/p&gt;

    &lt;p&gt;而今天我们这个引路人就是Tor（The Onion Router），直译过来为“洋葱路由”。既然已经通过 Tor 打开了“深网”的大门，那么让我们就将其一窥究竟，因为广大的深网网站都无法被搜索引擎收录，所以我们必须要找到一个收录各类深网网站的索引站点，“Hidden Wiki”就是其中较为出名的一个，它收录了各类深网网站地址。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Hidden wiki:
    &lt;ol&gt;
      &lt;li&gt;http://zqktlwi4fecvo6ri.onion/wiki/&lt;/li&gt;
      &lt;li&gt;http://torlinkbgs6aabns.onion/&lt;/li&gt;
      &lt;li&gt;http://wikitjerrta4qgz4.onion/&lt;/li&gt;
      &lt;li&gt;http://jh32yv5zgayyyts3.onion/&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Tor&quot;&gt;gentoo wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://gentoo-en.vfose.ru/wiki/Tor&quot;&gt;gentoo-en&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Tor&quot;&gt;arch wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.gonewto.com/?post/zm2bw2&quot;&gt;cn link1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://roxhaiy.wordpress.com/2015/01/11/设置shadowsockstor多重代理/&quot;&gt;cn link2&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Snippets</title>
   <link href="/2016/02/20/snippets/"/>
   <updated>2016-02-20T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/02/20/snippets</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#abc&quot; id=&quot;markdown-toc-abc&quot;&gt;ABC&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#disk-usage&quot; id=&quot;markdown-toc-disk-usage&quot;&gt;disk usage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#arithmatic-operation&quot; id=&quot;markdown-toc-arithmatic-operation&quot;&gt;arithmatic operation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#if-string-comparision&quot; id=&quot;markdown-toc-if-string-comparision&quot;&gt;if string comparision&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#apg&quot; id=&quot;markdown-toc-apg&quot;&gt;apg&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#dig&quot; id=&quot;markdown-toc-dig&quot;&gt;dig&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#find&quot; id=&quot;markdown-toc-find&quot;&gt;find&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#bulk-rename&quot; id=&quot;markdown-toc-bulk-rename&quot;&gt;Bulk rename&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#number-range&quot; id=&quot;markdown-toc-number-range&quot;&gt;Number range&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#netstat&quot; id=&quot;markdown-toc-netstat&quot;&gt;netstat&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ln&quot; id=&quot;markdown-toc-ln&quot;&gt;ln&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#encodingcharset-conversion&quot; id=&quot;markdown-toc-encodingcharset-conversion&quot;&gt;Encoding/charset conversion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cr-lflf&quot; id=&quot;markdown-toc-cr-lflf&quot;&gt;CR-LF/LF&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#detect-line-ending&quot; id=&quot;markdown-toc-detect-line-ending&quot;&gt;Detect line ending:&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#conversion&quot; id=&quot;markdown-toc-conversion&quot;&gt;Conversion&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#bom&quot; id=&quot;markdown-toc-bom&quot;&gt;BOM&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#remove-whitespace&quot; id=&quot;markdown-toc-remove-whitespace&quot;&gt;Remove whitespace&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#empty-line&quot; id=&quot;markdown-toc-empty-line&quot;&gt;Empty line&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#newline&quot; id=&quot;markdown-toc-newline&quot;&gt;newline&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#read-line-by-line&quot; id=&quot;markdown-toc-read-line-by-line&quot;&gt;read line by line&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#darkhttpd&quot; id=&quot;markdown-toc-darkhttpd&quot;&gt;darkhttpd&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ssl-cert&quot; id=&quot;markdown-toc-ssl-cert&quot;&gt;SSL cert&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#curlwget&quot; id=&quot;markdown-toc-curlwget&quot;&gt;curl/wget&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#mtrping&quot; id=&quot;markdown-toc-mtrping&quot;&gt;mtr/ping&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#image-crop-and-keep-aspect-ratio&quot; id=&quot;markdown-toc-image-crop-and-keep-aspect-ratio&quot;&gt;Image crop and keep aspect ratio&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;abc&quot;&gt;ABC&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; input.file
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; l input.file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;disk-usage&quot;&gt;disk usage&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# disk usage&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;du&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-hsc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; file1 dir1
&lt;span class=&quot;nb&quot;&gt;du&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-hsc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# disk free&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;arithmatic-operation&quot;&gt;arithmatic operation&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;5.3025^2&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;4.871 | bc
bc &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;100*0.13&apos;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;BEGIN {print 100/3.5}&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;if-string-comparision&quot;&gt;if string comparision&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; equals to &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$str1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; contains &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else
  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; has nothing to do with &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pay attention to &lt;em&gt;quote&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;apg&quot;&gt;apg&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# apg -a1 -n1 -m16 -MSNCL -k&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;dig&quot;&gt;dig&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# dig @dns-server -p 53 www.example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;find&quot;&gt;find&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; /path/to/search &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-iname&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;*filename*&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; /path/to/search &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-iname&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*filename*&apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; /path/to/search &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-iname&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*.apk&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%f&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-fv&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; /path/to/copy &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find APPs/ &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-iname&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*.apk&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;for file; do file=&quot;${file##*/}&quot;; mkdir -p ROM/system/preset_apps/&quot;${file%.apk}&quot;; cp APPs/&quot;${file}&quot; ROM/system/preset_apps/&quot;${file%.*}&quot;; done&apos;&lt;/span&gt; bash &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; +
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nt&quot;&gt;-P&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;history&lt;/span&gt;/ &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*.HEIC&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;for file; do mv -v &quot;$file&quot; &quot;${file%%.*}.heic&quot;; done&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;bash&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; +
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find ROM/system/media/wallpaper/ &lt;span class=&quot;nt&quot;&gt;-depth&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-path&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*/wallpaper_15.png&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-delete&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find ROM/system/media/wallpaper/ &lt;span class=&quot;nt&quot;&gt;-depth&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; d &lt;span class=&quot;nt&quot;&gt;-empty&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-delete&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-iname&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*abc*&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;mv &quot;$0&quot; &quot;${0/abc/def}&quot;&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;_pkg_name
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*.jpg&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*.png&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;for img; do mv &quot;$img&quot; pics/&quot;${_pkg_name}&quot;; done&apos;&lt;/span&gt; bash &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; +
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*.jpg&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;for f; do mv $f ${f//&quot;$0&quot;}; done&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;$&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\3&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;02&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\2&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;40&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; +
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*.pgn&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-print0&lt;/span&gt; | xargs &lt;span class=&quot;nt&quot;&gt;-0&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n4&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-P4&lt;/span&gt; mawk &lt;span class=&quot;s1&quot;&gt;&apos;/Result/ { split($0, a, &quot;-&quot;); res = substr(a[1], length(a[1]), 1); if (res == 1) white++; if (res == 0) black++; if (res == 2) draw++ } END { print white+black+draw, white, black, draw }&apos;&lt;/span&gt; | mawk &lt;span class=&quot;s1&quot;&gt;&apos;{games += $1; white += $2; black += $3; draw += $4; } END { print games, white, black, draw }&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Dont forget the quotes to prevent shell expansion.&lt;/li&gt;
  &lt;li&gt;In the fourth example, the random string argument (i.e. &lt;em&gt;bash&lt;/em&gt;) preceding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{}&lt;/code&gt; is a &lt;strong&gt;must&lt;/strong&gt;. It serves as the very first argument for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-exec bash&lt;/code&gt; command. You can either quote it or not.&lt;/li&gt;
  &lt;li&gt;Variables (i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_pkg_name&lt;/code&gt;) should be exported before calling &apos;find&apos; as it spawns a new process.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-print0&lt;/code&gt; prints the full file name on the standard output, followed by a &lt;em&gt;null character&lt;/em&gt; (instead of the newline character that -print uses). This allows file names that contain newlines or other types of white space to be correctly interpreted by programs that process the find output. This option corresponds to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-0&lt;/code&gt; option of &lt;em&gt;xargs&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sometimes we want to search for directories instead of files. As the very first result is the root directory itself, we may want to omit the &apos;bash&apos; arbitrary string such that the root directory becomes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$0&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; d &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*figs*&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;for d; do rm -rf $d; done&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; +
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nt&quot;&gt;-H&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; d &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*figs*&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;for d; do rm -rf $d; done&apos;&lt;/span&gt; bash &lt;span class=&quot;s1&quot;&gt;&apos;{}&apos;&lt;/span&gt; +
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The second version will remove current directory as well. Removing the &apos;bash&apos; string will leaves it untouched.&lt;/p&gt;

&lt;h1 id=&quot;bulk-rename&quot;&gt;Bulk rename&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.jpg&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%04d.jpg&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;#04 pad to length of 4&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;mv&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$new&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;a+1
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;number-range&quot;&gt;Number range&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# -w means equal width&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;seq&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; 5 20
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;netstat&quot;&gt;netstat&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;netstat &lt;span class=&quot;nt&quot;&gt;-npeatu&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ss &lt;span class=&quot;nt&quot;&gt;-npeatu&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;net-tools&lt;/em&gt; is deprecated in favor of &lt;em&gt;iproute2&lt;/em&gt;. The alternative to &lt;em&gt;netstat&lt;/em&gt; is &lt;em&gt;ss&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;ln&quot;&gt;ln&lt;/h1&gt;

&lt;p&gt;Soft/symbolic link (symlink) points to file&apos;s directory entry while hard link points to file&apos;s inode. No matter of symlink or hard link, both are real but special files.&lt;/p&gt;

&lt;p&gt;When delete a symlink file, the orginal file is not touched. However, to delete a hard link file, the original file&apos;s hard link references count will be decreased by 1. If the final count equal to 0, then the original file is deleted as well.&lt;/p&gt;

&lt;h1 id=&quot;encodingcharset-conversion&quot;&gt;Encoding/charset conversion&lt;/h1&gt;

&lt;p&gt;Charset is a set of &lt;em&gt;character&lt;/em&gt; entities while encoding is its representation in the terms of &lt;em&gt;bytes&lt;/em&gt; and &lt;em&gt;bits&lt;/em&gt;.  In Enca, the word encoding means the same as &lt;em&gt;representation of text&lt;/em&gt;, i.e. the relation between sequence of character entities constituting the text and sequence of bytes (bits) constituting the file.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;enca/file filename, detect encoding
   &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;enconv filename, convert to &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;locale&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
   &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;enconv/enca &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; gb2312 filename, convert to specified encoding
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;enca/enconv&lt;/em&gt; is a tool superior to &lt;em&gt;iconv&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;It does NOT make backup.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;cr-lflf&quot;&gt;CR-LF/LF&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;CR: Carriage Return, &apos;\r&apos;, &apos;\o015&apos;, &apos;\xd&apos;.&lt;/li&gt;
  &lt;li&gt;LF: Line Feeding, &apos;\n&apos;, &apos;\o12&apos;, &apos;\xa&apos;.&lt;/li&gt;
  &lt;li&gt;Some DOS files are ended with CR-LF, while others are LF-CR.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;detect-line-ending&quot;&gt;Detect line ending:&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;hexdump &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; input.file, detect line ending
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; l input.file
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;file input.file
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;od&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; c input.file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;conversion&quot;&gt;Conversion&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;app-text/dos2unix&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dos2unix/unix2dos &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; input.file, &lt;span class=&quot;s1&quot;&gt;&apos;-b&apos;&lt;/span&gt; makes a backup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;perl&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;perl &lt;span class=&quot;nt&quot;&gt;-pi&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/\r//g&apos;&lt;/span&gt; input.file
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;perl &lt;span class=&quot;nt&quot;&gt;-pi&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/\n/\r\n/g&apos;&lt;/span&gt; input.file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;sed&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;s/\r$//g&apos;&lt;/span&gt; input.file
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;s/$/\r/g&apos;&lt;/span&gt; input.file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;tr&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\r&apos;&lt;/span&gt; &amp;lt; input.file &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; output.file, cannot &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;it the other way round
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;nano&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Type Ctrl-O and before confirming, type Alt-D (DOS) or Alt-M (Mac) to change the format.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Refer to &lt;a href=&quot;http://mywiki.wooledge.org/BashFAQ/052&quot;&gt;remove CRs from CR-LF line terminators&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;bom&quot;&gt;BOM&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;1s/^\xEF\xBB\xBF//&apos;&lt;/span&gt; orig.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;remove-whitespace&quot;&gt;Remove whitespace&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;echo&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# `echo&apos; without double quotes; squeeze sequencial spaces within the string to single one&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;   how   are	you   &quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;sed&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; how    are    you   &quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/^[ \t]*//&apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/[ \t]*$//&apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/[[:space:]]*$//&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/^[ \t]*//;s/[ \t]*$//&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$str&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;awk/gawk&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# even sequencial tabs (maybe other blank characters) are squeezed to single space within string&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{$1=$1};1&apos;&lt;/span&gt; file
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{$1=$1;print}&apos;&lt;/span&gt; file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;empty-line&quot;&gt;Empty line&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/^[[:space:]]*$/d&apos;&lt;/span&gt; file.txt
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/^\s*$/d&apos;&lt;/span&gt; file.txt
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/^\s*$//g&apos;&lt;/span&gt; file.txt   &lt;span class=&quot;c&quot;&gt;# failure as empty line replaced by a blank line&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; file.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;newline&quot;&gt;newline&lt;/h1&gt;

&lt;p&gt;Replace newline with another character:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\n&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;,&apos;&lt;/span&gt; &amp;lt; file.txt

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/\n/,/g&apos;&lt;/span&gt; file.txt     &lt;span class=&quot;c&quot;&gt;# failure as sed read line but does not include the line terminator - newline&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-z&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/\n/,/g&apos;&lt;/span&gt; file.txt  &lt;span class=&quot;c&quot;&gt;# tell sed to use NULL as line terminator, so that newline is included when reading a line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;read-line-by-line&quot;&gt;read line by line&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/workspace/bash/zh.txt
&lt;span class=&quot;nv&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/workspace/bash/zh.dict.yaml

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$output&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;$&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; left right
&lt;span class=&quot;k&quot;&gt;do
    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;$&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;word &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
	if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ā&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ā/a/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;1&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;á&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/á/a/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;2&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ǎ&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ǎ/a/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;3&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;à&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/à/a/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;4&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ē&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ē/e/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;1&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;é&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/é/e/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;2&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ě&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ě/e/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;3&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;è&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/è/e/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;4&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ō&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ō/o/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;1&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ó&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ó/o/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;2&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ǒ&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ǒ/o/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;3&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ò&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ò/o/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;4&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ī&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ī/i/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;1&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;í&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/í/i/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;2&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ǐ&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ǐ/i/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;3&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ì&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ì/i/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;4&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ū&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ū/u/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;1&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ú&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ú/u/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;2&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ǔ&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ǔ/u/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;3&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ù&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ù/u/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;4&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ǖ&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ǖ/ü/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;1&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ǘ&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ǘ/ü/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;2&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ǚ&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ǚ/ü/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;3&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ǜ&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/ǜ/ü/&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$word&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
	    &lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;4&lt;span class=&quot;s1&quot;&gt;&apos; &apos;&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;fi
    done
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/[[:space:]]*$//&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$output&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt; &amp;lt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IFS=&lt;/code&gt; option before &lt;em&gt;read&lt;/em&gt; command prevents leading/trailing whitespace from being trimmed.&lt;/li&gt;
  &lt;li&gt;The -r option passed to &lt;em&gt;read&lt;/em&gt; command prevents backslash escapes from being interpreted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/bin/bash
file=&quot;/etc/passwd&quot;
while IFS=: read -r f1 f2 f3 f4 f5 f6 f7
do
        # display fields using f1, f2,..,f7
        printf &apos;Username: %s, Shell: %s, Home Dir: %s\n&apos; &quot;$f1&quot; &quot;$f7&quot; &quot;$f6&quot;
done &amp;lt;&quot;$file&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Third version:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;input:&quot;&lt;/span&gt; line
&lt;span class=&quot;k&quot;&gt;do
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;  &amp;lt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:-&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;/dev/stdin&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Read from &lt;em&gt;stdin&lt;/em&gt; or from a file parameter.&lt;/p&gt;

&lt;p&gt;Here is an elegant version, just reading a line:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;infd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0 &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; : &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;infd&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&amp;lt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;input:&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; line &amp;lt;&amp;amp;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;infd&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# read -u $infd -r line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;darkhttpd&quot;&gt;darkhttpd&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./darkhttpd ~/workspace/public_html &lt;span class=&quot;nt&quot;&gt;--pidfile&lt;/span&gt; ~/workspace/httpd_traces/httpd.pid &lt;span class=&quot;nt&quot;&gt;--daemon&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--maxconn&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--no-listing&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--log&lt;/span&gt; ~/workspace/httpd_traces/access.log &lt;span class=&quot;nt&quot;&gt;--forward&lt;/span&gt; example.com:8080 http://www.example.com:8080
or
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./darkhttpd ~/workspace/public_html &lt;span class=&quot;nt&quot;&gt;--maxconn&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--no-listing&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--log&lt;/span&gt; ~/workspace/httpd_traces/access.log &lt;span class=&quot;nt&quot;&gt;--forward&lt;/span&gt; example.com:8080 http://www.example.com:8080 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;ssl-cert&quot;&gt;SSL cert&lt;/h1&gt;

&lt;p&gt;By &lt;em&gt;openssl s_client&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; chat.freenode.net:6697 &amp;lt;/dev/null
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; chat.freenode.net:6697 &amp;lt;/dev/null | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ne&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; freenode.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-showcerts&lt;/code&gt; show all certificates in the chain, including the CA certificate, otherwise only the server certificate was downloaded.&lt;/li&gt;
  &lt;li&gt;If the remote server is using SNI (that is, sharing multiple SSL hosts on a single IP address) you will also need to send the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-servername&lt;/code&gt; in order to get the right certificate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By &lt;em&gt;gnutls-cli&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gnutls-cli &lt;span class=&quot;nt&quot;&gt;--print-cert&lt;/span&gt; chat.freenode.net:6697 &amp;lt;/dev/null
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gnutls-cli &lt;span class=&quot;nt&quot;&gt;--print-cert&lt;/span&gt; chat.freenode.net:6697 &amp;lt;/dev/null | &lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ne&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; freenode.pem
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gnutls-cli &lt;span class=&quot;nt&quot;&gt;--print-cert&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--save-cert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;freenode.pem chat.freenode.net:6697 &amp;lt;/dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--sni-hostname&lt;/code&gt; serves the same role as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-servername&lt;/code&gt; of &lt;em&gt;openssl s_client&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;gnutls-cli&lt;/em&gt; always downloads the full certificate chain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Examine the certificate downloaded:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;freenode.pem&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; less freenode.pem
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;openssl x509 &lt;span class=&quot;nt&quot;&gt;-noout&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-text&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; freenode.pem
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;openssl x509 &lt;span class=&quot;nt&quot;&gt;-noout&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sha256&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-fingerprint&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; freenode.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;curlwget&quot;&gt;curl/wget&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;Use curl/wget to test web/ftp service&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; http://www.example.com
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;wget &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; http://www.example.com &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Print the headers sent by HTTP servers and responses sent by FTP servers&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; http://www.example.com
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt; http://www.example.com &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Fetch the headers only&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; http://www.example.com &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Include the HTTP response headers &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the output&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--trace&lt;/span&gt;/--trace-ascii test.log http://www.example.com &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Enables a full trace dump of all incoming and outgoing data, including descriptive information, to the given output file&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--socks5&lt;/span&gt; 127.0.0.1:1080 &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; https://www.youtube.com &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Test socks5 proxy&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;--socks5-hostname&lt;/span&gt; 127.0.0.1:1080 &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; https://www.youtube.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Use curl to download a file&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-OLv&lt;/span&gt; http://www.example.com/file.txt
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;curl &lt;span class=&quot;nt&quot;&gt;-Lv&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; new_file.txt http://www.example.com/file.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;mtrping&quot;&gt;mtr/ping&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mtr &lt;span class=&quot;nt&quot;&gt;-rw&lt;/span&gt; 12.34.56.78
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;image-crop-and-keep-aspect-ratio&quot;&gt;Image crop and keep aspect ratio&lt;/h1&gt;

&lt;p&gt;Filter the images:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;kwdes.txt&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Save as UTF-16 txt&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# C-x RET r, revert-buffer-with-coding-system, UTF-8&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;s/\xC2\xA0//g&apos;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# non-breaking space&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;s/\r//g&apos;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# crlf to lf&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;s/[[:blank:]]*$//&apos;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# leading white spaces&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;s/^[[:blank:]]*//&apos;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# trailing white spaces&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;s1&quot;&gt;&apos;/^$/d&apos;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# empty lines&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt;.bak &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;1d&apos;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# delete the 1st line&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;wc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#mkdir -p $(cut -d$&apos;\t&apos; -f1 &quot;${_input}&quot;)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#awk -F&apos;\t&apos; &apos;FNR==linum { print $1, $4, $5 }&apos; &quot;${_input}&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#awk -F&apos;\t&apos; &apos;FNR==linum { printf(&quot;%s\t%s\t%s\n&quot; $1, $4, $5) }&apos; &quot;${_input}&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#awk -F&apos;\t&apos; &apos;BEGIN { OFS=FS } FNR==linum { print $1, $2, $3 }&apos; &amp;lt;&amp;lt;&amp;lt; $&apos;a\tb\tc\td\n123\n&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Crop the images:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# https://www.zedge.net/find/wallpapers/keyword, 8 * 1080x1920, com.uphone.wallpaperkeyword_description/keyword_date_num.jpg&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# https://wallpaperscraft.com/catalog/keyword/1440x2560/page2&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# https://wall.alphacoders.com/search.php?search=Minecraft#sorting_options&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# icon_{1024*500,180*120}.jpg, ic_launcher_{512,192,148,96,72,48}.jpg&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# magick -verbose input.jpg -trim -resize &quot;1024x500^&quot; -gravity center -extent &quot;1024x500+0+0&quot; +repage output.jpg # -extent -or -crop&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Parameters: line number &amp;gt; 1, selected filename&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;shopt&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; extglob
&lt;span class=&quot;c&quot;&gt;#shopt -s nullglob&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;_workspace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/WLshare&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_workspace&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;kwdes.txt&quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;_linum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_linum&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &amp;lt; 1 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;line number starts from 1&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exit
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fi

&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;\t&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;linum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_linum&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FNR==linum {print $1}&apos;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;//[[&lt;/span&gt;:blank:]]/&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Keyword: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;_pkg_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-F&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;\t&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;linum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_linum&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;FNR==linum {print $4}&apos;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_input&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Package name: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_pkg_name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_pkg_name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;_select&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$2&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Select: &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_select&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;_icon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;1024x500 180x120&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_icon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    &lt;/span&gt;magick &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_select&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-resize&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-gravity&lt;/span&gt; center &lt;span class=&quot;nt&quot;&gt;-extent&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;+0+0&quot;&lt;/span&gt; +repage &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;s2&quot;&gt;&quot;icon_&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%x*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.jpg&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_launcher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;512x512 192x192 148x148 96x96 72x72 48x48&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_launcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    &lt;/span&gt;magick &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_select&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-resize&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-gravity&lt;/span&gt; center &lt;span class=&quot;nt&quot;&gt;-extent&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;+0+0&quot;&lt;/span&gt; +repage &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;s2&quot;&gt;&quot;ic_launcher_&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;%x*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.jpg&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done

&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; +&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.jpg|&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.png&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_pkg_name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; 2&amp;gt;/dev/null
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;/&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_pkg_name&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1080x1920&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;_counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;f &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.+&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;jpg|png&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
	&lt;/span&gt;magick &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-resize&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_size&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;^&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-gravity&lt;/span&gt; center &lt;span class=&quot;nt&quot;&gt;-extent&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_size&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;+0+0&quot;&lt;/span&gt; +repage &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;mv&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_keyword&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;_&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_counter&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.jpg&quot;&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;_counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;_counter &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi
done&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# { cd ../../; rm -f -- *.+(jpg|png); }&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;done!&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>GnuPG</title>
   <link href="/2016/02/13/gnupg/"/>
   <updated>2016-02-13T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/02/13/gnupg</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#anatomy&quot; id=&quot;markdown-toc-anatomy&quot;&gt;Anatomy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#examine-key&quot; id=&quot;markdown-toc-examine-key&quot;&gt;Examine Key&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#create-key&quot; id=&quot;markdown-toc-create-key&quot;&gt;Create key&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#edit-key&quot; id=&quot;markdown-toc-edit-key&quot;&gt;Edit key&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#revocation&quot; id=&quot;markdown-toc-revocation&quot;&gt;Revocation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#export-key&quot; id=&quot;markdown-toc-export-key&quot;&gt;Export key&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#import-keys&quot; id=&quot;markdown-toc-import-keys&quot;&gt;Import keys&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#upload-to-keyservers&quot; id=&quot;markdown-toc-upload-to-keyservers&quot;&gt;Upload to keyservers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#key-management&quot; id=&quot;markdown-toc-key-management&quot;&gt;Key Management&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#using-trust-to-validate-keys&quot; id=&quot;markdown-toc-using-trust-to-validate-keys&quot;&gt;Using trust to validate keys&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#validity-level&quot; id=&quot;markdown-toc-validity-level&quot;&gt;Validity Level&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#usage&quot; id=&quot;markdown-toc-usage&quot;&gt;Usage&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#sign&quot; id=&quot;markdown-toc-sign&quot;&gt;sign&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#verify&quot; id=&quot;markdown-toc-verify&quot;&gt;verify&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#encrypt&quot; id=&quot;markdown-toc-encrypt&quot;&gt;encrypt&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#sign-and-encrypt&quot; id=&quot;markdown-toc-sign-and-encrypt&quot;&gt;sign and encrypt&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#expire&quot; id=&quot;markdown-toc-expire&quot;&gt;expire&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gpgconf&quot; id=&quot;markdown-toc-gpgconf&quot;&gt;gpg.conf&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gpg-agent&quot; id=&quot;markdown-toc-gpg-agent&quot;&gt;gpg-agent&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#pinentry&quot; id=&quot;markdown-toc-pinentry&quot;&gt;pinentry&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#configuring-gpg-agent&quot; id=&quot;markdown-toc-configuring-gpg-agent&quot;&gt;configuring gpg-agent&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#launch-agent&quot; id=&quot;markdown-toc-launch-agent&quot;&gt;launch agent&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#automation&quot; id=&quot;markdown-toc-automation&quot;&gt;Automation&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ssh-mode&quot; id=&quot;markdown-toc-ssh-mode&quot;&gt;SSH mode&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#gpg_agent_info&quot; id=&quot;markdown-toc-gpg_agent_info&quot;&gt;GPG_AGENT_INFO&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#refs&quot; id=&quot;markdown-toc-refs&quot;&gt;Refs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the previous post SSH, I talked about &lt;em&gt;secure connection&lt;/em&gt; (i.e. remote login) on the Internet. Now you will see how GnuPG (an implementation of OpenPGP) is used to &lt;em&gt;encrypt/decrypt&lt;/em&gt; messages (i.e. email, documents). To use &lt;em&gt;gpg&lt;/em&gt;, read &lt;a href=&quot;https://www.gnupg.org/gph/en/manual.html&quot;&gt;official guide&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;anatomy&quot;&gt;Anatomy&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Public key and private key.
    &lt;ol&gt;
      &lt;li&gt;A document is encrpted by your public key and decrpted by your private key.&lt;/li&gt;
      &lt;li&gt;A document is signed by your privated key and verfied by your public key.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Primary key and subkey.
    &lt;ol&gt;
      &lt;li&gt;Primary key pair is your &lt;em&gt;online identity&lt;/em&gt;, usually used for signature.&lt;/li&gt;
      &lt;li&gt;A subkey pair is bond to the primary key, usually used for signature or encryption. We can bind many subkeys to the primary key for different purposes.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href=&quot;https://serverfault.com/a/399366/172375&quot;&gt;A rule of thumb&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;never ever sign and ecrypt using the same key&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;examine-key&quot;&gt;Examine Key&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--list-keys&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--list-options&lt;/span&gt; show-usage &lt;span class=&quot;nt&quot;&gt;--with-fingerprint&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--with-colons&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--list-secret-keys&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--export&lt;/span&gt; &amp;lt;keyid | uid&amp;gt; | gpg &lt;span class=&quot;nt&quot;&gt;--list-packets&lt;/span&gt;

gpg: directory &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/home/jim/.gnupg&lt;span class=&quot;s1&quot;&gt;&apos; created
gpg: new configuration file `/home/jim/.gnupg/gpg.conf&apos;&lt;/span&gt; created
gpg: WARNING: options &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;/home/jim/.gnupg/gpg.conf&lt;span class=&quot;s1&quot;&gt;&apos; are not yet active during this run
gpg: keyring `/home/jim/.gnupg/pubring.gpg&apos;&lt;/span&gt; created
gpg: /home/jim/.gnupg/trustdb.gpg: trustdb created
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will try to list available GPG keys on system. If it is the first time to run &lt;em&gt;gpg&lt;/em&gt;, some directories and files essential to the correct operation and implementation will be created.&lt;/p&gt;

&lt;h1 id=&quot;create-key&quot;&gt;Create key&lt;/h1&gt;

&lt;p&gt;The very first step of using GnuPG is &lt;em&gt;creating a key pair&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here is what I will do:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Choose default key method: (1) RSA and RSA (default).&lt;/li&gt;
  &lt;li&gt;Keysize - the longest - 4096 bits.&lt;/li&gt;
  &lt;li&gt;Key valid for one year&lt;/li&gt;
  &lt;li&gt;Provide name and email address to identify the key.&lt;/li&gt;
  &lt;li&gt;Provide a &lt;em&gt;passphrase&lt;/em&gt; to protect the private key. The public key don&apos;t need protection.&lt;/li&gt;
  &lt;li&gt;Get the key ID: the last 64 bits &lt;em&gt;fingerprint&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# require parameters&lt;/span&gt;
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--full-generate-key&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# use default parameters&lt;/span&gt;
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--gen-key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;use default key parameter&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;The option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--full-gen-key&lt;/code&gt; is interactive asking for key parameters like exipration date etc.&lt;/li&gt;
  &lt;li&gt;GnuPG will take several minutes to generate the key pair. You&apos;d better moving the mouse, browsing the web, or having streaming audio in the background to generate noise, which will help speed up the process.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By default, a primary key and a subkey are created separately for signature and encryption respectively.&lt;/p&gt;

&lt;h1 id=&quot;edit-key&quot;&gt;Edit key&lt;/h1&gt;

&lt;p&gt;At any moment, we can update passphrase, user id, subkey, etc.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--edit-key&lt;/span&gt; &amp;lt;keyid | uid&amp;gt;

gpg&amp;gt; &lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Existing user ID (comment included) can &lt;em&gt;not&lt;/em&gt; be modified after creation. But you can add or delete user ID instead. We can set a user ID to be the &quot;primary user ID&quot; (top in the ID list).&lt;/p&gt;

&lt;h1 id=&quot;revocation&quot;&gt;Revocation&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;Newer GnuPG version will issue revocation certificate upon key creation. However, it&apos;s always a good idea to create a new revocation certificate as long as you still access to the private key, providing a strong revocation description.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create a revocation certificate. Doing this allow you to revoke the key in case something nasty happens (lose the key; superseded; compromised etc.).&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; 12345678-revocation.asc &lt;span class=&quot;nt&quot;&gt;--gen-revoke&lt;/span&gt; 12345678
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you don&apos;t give &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--output 12345678-revocation.asc&lt;/code&gt;, the revocation certificate will be printed on screen.&lt;/p&gt;

&lt;p&gt;Please move it to a medium which you can hide away; if Mallory gets access to this certificate he can use it to make your key unusable. It is smart to print this certificate and store it away, just in case your media become unreadable.  But have some caution:  The print system of your machine might store the data and make it available to others!&lt;/p&gt;

&lt;p&gt;Later on, suppose you want to revoke the key,&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; 12345678-revocation.asc
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--keyserver&lt;/span&gt; pgp.mit.edu &lt;span class=&quot;nt&quot;&gt;--send-keys&lt;/span&gt; 12345678
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Issuing this command imports the revocation into your keyring, revoking your key locally.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;This sends the revoked key to key server to let your friends know.&lt;/p&gt;

    &lt;p&gt;If it succeeds, you&apos;ll get the message:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;gpg: success sending to `pgp.mit.edu&apos; (status=200)&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;If you check your key&apos;s verbose index page on &lt;em&gt;pgp.mit.edu&lt;/em&gt;, you&apos;ll see KEY REVOKED on the first line of the details.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;New version of GnuPG creates revocation certificate automaticall unpon key creation in &lt;em&gt;~/.gnupg/openpgp-revocs.d&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;export-key&quot;&gt;Export key&lt;/h1&gt;

&lt;p&gt;Now it&apos;s time to distribute the public key.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# export public key&lt;/span&gt;
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--export&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; public.pgp email@gmx.com
&lt;span class=&quot;c&quot;&gt;# export private key&lt;/span&gt;
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--armor&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--export-secret-keys&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--export-options&lt;/span&gt; backup &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; key-backup.pgp email.gmx.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;By default, the public key will be exported to STDOUT. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--output name.pub&lt;/code&gt; exports to file. It&apos;s recommended to distribute this file with the &lt;em&gt;fingerprint&lt;/em&gt; attached.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--armor&lt;/code&gt; tells &lt;em&gt;gpg&lt;/em&gt; to generate ASCII &lt;em&gt;text&lt;/em&gt; output instead of default &lt;em&gt;binary&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We export private key (public key included) for backup or moving keys around.&lt;/p&gt;

    &lt;p&gt;A reasonable way to achieve a long term backup of OpenPGP (GnuPG, PGP, etc) keys is to &lt;a href=&quot;http://www.jabberwocky.com/software/paperkey/&quot;&gt;print them out on paper&lt;/a&gt;. Paper and ink have amazingly long retention qualities - far longer than the magnetic or optical means that are generally used to back up computer data.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;import-keys&quot;&gt;Import keys&lt;/h1&gt;

&lt;p&gt;Once you get a copy of the exported public key of your friend, add it to your public keyring.&lt;/p&gt;

&lt;p&gt;Pay attention to verify &lt;em&gt;fingerprint&lt;/em&gt; to avoid receiving a forged public key.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; friend.pub
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--edit-key&lt;/span&gt; friend-key, &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;enter sub-command&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
   list - list the key information.
   fpr - print fingerprint of imported key &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;same as &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--fingerprint&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
   sign - sign your friend&lt;span class=&quot;s1&quot;&gt;&apos;s public key by your private key.
   check - check the signature.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After importing the public key, now you can encrypt message to friend or to certify key&apos;s owner&apos;s signature.&lt;/p&gt;

&lt;p&gt;We can also import a secret key:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--import&lt;/span&gt; key-backup.pgp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;upload-to-keyservers&quot;&gt;Upload to keyservers&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--export&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--import&lt;/code&gt; distribute keys between friends directly. There are many public key servers where you can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--recv-keys&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--send-keys&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--search-keys&lt;/code&gt;. Since  version  2.1  of GnuPG, &lt;em&gt;dirmngr&lt;/em&gt; takes care of accessing the OpenPGP keyservers.&lt;/p&gt;

&lt;p&gt;All these public key servers will exchange keys periodically. Most of the time, you only need to focus on one of them. You can specify &lt;em&gt;keyserver&lt;/em&gt; in &lt;em&gt;~/.gnupg/dirmngr.conf&lt;/em&gt; or on command line by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--keyserver&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--search-keys&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;jim gray&quot;&lt;/span&gt;

jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--recv-key&lt;/span&gt; keyid
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--send-key&lt;/span&gt; keyid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;key-management&quot;&gt;Key Management&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Key
    &lt;ol&gt;
      &lt;li&gt;Your own key pair - public/private key.&lt;/li&gt;
      &lt;li&gt;Friends&apos;/organizations&apos; public keys. Imported from key file or received from key servers.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Utility
    &lt;ol&gt;
      &lt;li&gt;Public key is distributed over the Internet, i.e. sent to key servers or handed over to friends manually.
        &lt;ol&gt;
          &lt;li&gt;People encrypt messages before sending to you.&lt;/li&gt;
          &lt;li&gt;People certify your signature.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Keep private key confidentially.
        &lt;ol&gt;
          &lt;li&gt;Use it to decrypt message received.&lt;/li&gt;
          &lt;li&gt;
            &lt;p&gt;Sign documents before publication.&lt;/p&gt;

            &lt;p&gt;A special case is to sign public keys from friends/key servers to validate them.&lt;/p&gt;
          &lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Validity
    &lt;ol&gt;
      &lt;li&gt;Before using a key, make sure the key is owned by whom you would communicate with. Our own key pair is valid by default. But how about friends&apos; public keys? How to validate them?&lt;/li&gt;
      &lt;li&gt;Upon receiving a public key, &lt;em&gt;fingerprint&lt;/em&gt; is included which should be compared with what the owner claims (i.e. handed over to you). If it&apos;s a organization&apos;s public certificate, usually fingerprint is pasted on their official page along with public key certificate download link.&lt;/li&gt;
      &lt;li&gt;After confirmation the public key fingerprint, you &lt;em&gt;sign&lt;/em&gt; the public key with your private key. To manually &lt;em&gt;sign&lt;/em&gt; a key &lt;em&gt;directly&lt;/em&gt; is to &lt;em&gt;validate/certify&lt;/em&gt; a key.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;If a public key is not sign directly before usage, a &lt;em&gt;gpg&lt;/em&gt; warning comes out like this:&lt;/p&gt;

        &lt;blockquote&gt;
          &lt;p&gt;gpg: WARNING: This key is not certified with a trusted signature!&lt;/p&gt;
        &lt;/blockquote&gt;

        &lt;p&gt;&lt;em&gt;gpg&lt;/em&gt; detects that the key you are using has not been validated. You can check whether a key is valid by the output of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpg --list-keys&lt;/code&gt;. If there is an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[unknown]&lt;/code&gt; in front of the user&apos;s ID, the key is NOT valid in that you cannot determine if it&apos;s owned by the one claiming to own it.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Web of trust&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;validity&lt;/em&gt; and &lt;em&gt;trust&lt;/em&gt; are different thing. If you trust &lt;em&gt;somebody&lt;/em&gt;, you acutally accept the keys he signed as valid.
But what if you have got 100 public keys at hand? Sign manually one by one? OMG! GnuPG addresses this problem with a mechanism popularly known as the &lt;em&gt;web of trust&lt;/em&gt;. In the web of trust model, responsibility for &lt;em&gt;validating&lt;/em&gt; public keys can be delegated to people you &lt;em&gt;trust&lt;/em&gt;.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;For example, you get public keys: k1, k2, k3, … You manually / directly signed k1 with your private key and validate it. Meanwhile, k1 signed k2 and k3 directly as well. From the viewpoint of k1, k2 and k3 are valid keys. If you trust k1 fully (level 4, discussed below), then you trust k1&apos;s signing action on k2 and k3. You view k2 and k3 as valid as well though you do not sign them directly.&lt;/p&gt;

    &lt;p&gt;What the hell does trust mean? &lt;strong&gt;trust means the confidence on someone&apos;s capacities at signing/validating/certifying keys&lt;/strong&gt;.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Trust is subjective judgement on others&apos; capacity. You trust on somebody according to whether he verifies public fingerprint carefully, whether he is a master of GnuPG and PKI. The purpose of trust is to relieve you from signing/validating keys one by one manually.&lt;/li&gt;
      &lt;li&gt;Validity is the status of a key from viewpoint of you (your &lt;em&gt;gpg&lt;/em&gt; on system).&lt;/li&gt;
      &lt;li&gt;So &lt;em&gt;trust&lt;/em&gt; serves &lt;em&gt;validity&lt;/em&gt;. The trust relationship forms a web. &lt;em&gt;gpg&lt;/em&gt; determines a key&apos;s validity by this web of trust.&lt;/li&gt;
      &lt;li&gt;Trust has levels. You can trust Bob fully while  Alice partially.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;using-trust-to-validate-keys&quot;&gt;Using trust to validate keys&lt;/h2&gt;

&lt;p&gt;How &lt;em&gt;trust&lt;/em&gt; works? Recall &lt;em&gt;gpg&lt;/em&gt; sub-command &lt;em&gt;sign&lt;/em&gt; validates public keys. There is &lt;em&gt;trust&lt;/em&gt; sub-command to assign &lt;em&gt;trust level&lt;/em&gt; to a key&apos;s owner.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Trust has levels: &lt;em&gt;unknown, none, marginal, ful, ultimate&lt;/em&gt;. Level 0 (unkown) means you don&apos;t know the key&apos;s owner&apos;s capacity at validating keys, while 5 means trust ultimately. Never trust other&apos;s key ultimately! &lt;em&gt;ultimate&lt;/em&gt; is designated for your own key only. Details on trust levels, refer to reference 1.&lt;/li&gt;
  &lt;li&gt;Formerly, a key was considered valid only if you signed it personally.  A more flexible algorithm can now be used: a key K is considered valid if it meets two conditions:
    &lt;ol&gt;
      &lt;li&gt;it is signed by enough valid keys, meaning:
        &lt;ul&gt;
          &lt;li&gt;you have signed it personally,&lt;/li&gt;
          &lt;li&gt;it has been signed by one fully trusted key, or&lt;/li&gt;
          &lt;li&gt;it has been signed by three marginally trusted keys; and&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;the path of signed keys leading from K back to your own key is five steps or shorter.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;prerequisite&lt;/em&gt;: the parent key should be &lt;em&gt;fully valid&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Apart from the web of trust, there is also a tree of &lt;em&gt;signing&lt;/em&gt; on which only the first layer nodes of tree is signed by you directly! We cannot determine the validity of a node (key) on lower layers without the help of web of trust.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;validity-level&quot;&gt;Validity Level&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;prequisite&lt;/em&gt; in the algorithm: the parent key (signing key) shuld be &lt;em&gt;fully valid&lt;/em&gt;. Actually, validity also has levels - similar to trust.&lt;/p&gt;

&lt;p&gt;You can sign a key directly and check the result. In front of the user ID, you will find &lt;em&gt;[full]&lt;/em&gt;, means this key is fully valid. For example, you fully trust a marginal valid key k1 on the signing tree and k1 signs another key k2. k2 should NOT be regarded fully valid.&lt;/p&gt;

&lt;h1 id=&quot;usage&quot;&gt;Usage&lt;/h1&gt;

&lt;p&gt;If there exist multiple keys created, use CLI option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--default-key&lt;/code&gt; or configuration &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default-key&lt;/code&gt; to select the key.&lt;/p&gt;

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

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; message.sig &lt;span class=&quot;nt&quot;&gt;--sign&lt;/span&gt; message.txt
or
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--clearsign&lt;/span&gt; message.txt
or
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--detach-sig&lt;/span&gt; message.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;It uses your private key to sign.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The first output is binary format with original file compressed.&lt;/p&gt;

    &lt;p&gt;This is NOT a preferred way to sign documents.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The 2nd output will append signature to the end of original file without compression. This what we usually used to sign email.&lt;/p&gt;

    &lt;p&gt;But receiver has to recover orginal document from the signature file.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The 3rd will create a separate binary signature file without touching the original document. You can send the original file along with the signature file.&lt;/p&gt;

    &lt;p&gt;This is useful when the original document is large files.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;verify&quot;&gt;verify&lt;/h3&gt;

&lt;p&gt;Unpon get a signed message, we can just check the signature by &lt;em&gt;–verify&lt;/em&gt; or verify the signature and extract the original message concurrently by &lt;em&gt;–decrypt&lt;/em&gt;. To verify a detach signature, both the oirginal document and signature file must be present.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--verify&lt;/span&gt; message.sig
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--verify&lt;/span&gt; message.sig message
jim@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; message &lt;span class=&quot;nt&quot;&gt;--decrypt&lt;/span&gt; messag.sig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--encrypt&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--recipient&lt;/span&gt; recipient@example.com message.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Should specify who is the receiver by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--recipient&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;sign-and-encrypt&quot;&gt;sign and encrypt&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--sign&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--encrypt&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--recipient&lt;/span&gt; recipient@example.com message.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Output is binary format.&lt;/li&gt;
  &lt;li&gt;Cannot use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--clearsign&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--encrypt&lt;/code&gt; simutaneously.&lt;/li&gt;
  &lt;li&gt;There is no need for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--detach-sig&lt;/code&gt; in this case.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When receving a &lt;em&gt;secret.gpg&lt;/em&gt; file, you&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; original.txt &lt;span class=&quot;nt&quot;&gt;--decrypt&lt;/span&gt; secret.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;expire&quot;&gt;expire&lt;/h1&gt;

&lt;p&gt;Though keys can be set to never expire, you are recommended to set an expiration date since you can always extend the expiration date even after it has expired. This &quot;expiration&quot; is actually more of a safety valve or &quot;dead-man switch&quot; that will automatically trigger at some point. If you have access to the secret key material, you can untrigger it. The point is to setup something to disable your key in case you lose access to it (and have no revocation certificate).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ $ gpg --edit-key uid

gpg&amp;gt; expire
...
gpg&amp;gt; key 1
gpg&amp;gt; expire
...
gpg&amp;gt; save

~ $ gpg -k

~ $ gpg -K
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;The first &lt;em&gt;expire&lt;/em&gt; without selected key sets new exipiration date for primary key.&lt;/li&gt;
  &lt;li&gt;The second &lt;em&gt;expire&lt;/em&gt; with selected sub-key sets new expiration date for &lt;em&gt;key 1&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ohters can notice the expiration of your public key from key servers. For private keys, only you know it unless you give them to some bad guy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;gpgconf&quot;&gt;gpg.conf&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ~/.gnupg/gpg.conf

use-agent
pinentry-mode default
keyid-format 0xlong
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Any long CLI options can be a configuration entry by removing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--&lt;/code&gt; preifx.&lt;/p&gt;

&lt;h1 id=&quot;gpg-agent&quot;&gt;gpg-agent&lt;/h1&gt;

&lt;p&gt;Like the SSH Agent, GPG agent cache the private key passphrase. A user don&apos;t need to input passphrase each time using the key.&lt;/p&gt;

&lt;p&gt;Sometimes working with certain applications requires the use of a GPG key very frequently, which means that a passphrase must be frequently entered. In the past many applications supported a passphrase caching mechanism. This would make life easier for users because passphrases were automatically entered. However, this disallowed sharing this cache across programs (how secure would that be?) and forced applications to reinvent the wheel over and over again.&lt;/p&gt;

&lt;p&gt;In order for &lt;em&gt;apg-agent&lt;/em&gt; to works in Shell, we must correctly set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GPG_TTY&lt;/code&gt; as below.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ~/.bashrc&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GPG_TTY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tty&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;p&gt;GnuPG includes &lt;em&gt;gpg-agent&lt;/em&gt;. Pinentry (&lt;em&gt;app-crypt/pinentry&lt;/em&gt;) is a helper application that &lt;em&gt;gpg-agent&lt;/em&gt; uses to request the passphrase in a graphical window. It comes in three flavors: it can popup a window using the GTK+, QT, or curses libraries (depending on the USE flags set in &lt;em&gt;/etc/portage/make.conf&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;If &lt;em&gt;app-crypt/pinentry&lt;/em&gt; was installed with more than one popup window type, it is possible to choose between the windows with the eselect pinentry command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;laptop ~ &lt;span class=&quot;c&quot;&gt;# eselect pinentry list&lt;/span&gt;
Available pinentry binary implementations:
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1]   pinentry-gtk-2 &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2]   pinentry-curses
laptop ~ &lt;span class=&quot;c&quot;&gt;# eselect pinentry set 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;configuring-gpg-agent&quot;&gt;configuring gpg-agent&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ~/.gnupg/gpg-agent.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# called when prompt for passphrase the first time&lt;/span&gt;
pinentry-program /usr/bin/pinentry-gtk-2
&lt;span class=&quot;c&quot;&gt;# timeout 30 minutes&lt;/span&gt;
default-cache-ttl 1800
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now configure GnuPG to use an agent when appropriate. Edit &lt;em&gt;~/.gnupg/gpg.conf&lt;/em&gt; and add the following line:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# DEPRECATED!&lt;/span&gt;
use-agent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since GPG2, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use-agent&lt;/code&gt; is deprecated as GPG2 always require &lt;em&gt;agent&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;launch-agent&quot;&gt;launch agent&lt;/h2&gt;

&lt;p&gt;To launch agent manually:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ eval $(gpg-agent --sh --daemon --enable-ssh-support --write-env-file ${HOME}/.cache/gpg-agent-info)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the arguments are already provided in configuration file, they can be omitted. Attention, command line arguments will override those in configuration file.&lt;/p&gt;

&lt;p&gt;The command should be wrapped by &lt;em&gt;eval&lt;/em&gt;, otherwise environment variables would not be exported.&lt;/p&gt;

&lt;h2 id=&quot;automation&quot;&gt;Automation&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Refer to lastest &lt;em&gt;~/.bashrc&lt;/em&gt; for updates&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To launch GPG agent automatically on boot, add the command to startup scripts specially for servers (NO X/GUI). By default, Xfce4 starts the agent automatically on startup. Check by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ps -ef | grep -i gpg-agent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But if you launch an agent manually on consosle and then switch to start Xfce4, it will launch another agent for you. So check to launch agent in startup scripts like &lt;em&gt;.bashrc&lt;/em&gt; and &lt;em&gt;.bash_profile&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;(opt) Disable Xfce4 automation&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;xfconf-query &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; xfce4-session &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /startup/gpg-agent/enabled &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; bool &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;xfconf-query &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; xfce4-session &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /startup/ssh-agent/enabled &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; bool &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Edit &lt;em&gt;.bashrc&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Associate with existing gpg-agent
if [ -f &quot;${HOME}/.cache/gpg-agent-info&quot; ]; then
    . &quot;${HOME}/.cache/gpg-agent-info&quot;
    export GPG_AGENT_INFO
    export SSH_AUTH_SOCK
    export SSH_AGENT_PID
fi

# Start the gpg-agent if not already running
if ! pgrep -x -u &quot;${USER}&quot; gpg-agent &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
    eval `/usr/bin/gpg-agent --sh --daemon --enable-ssh-support --write-env-file &quot;${HOME}/.cache/gpg-agent-info&quot;`
fi

# Refresh gpg-agent tty in case user switches into an X session
gpg-connect-agent updatestartuptty /bye &amp;gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;With this script, the previous &lt;em&gt;ssh-find-agent&lt;/em&gt; is deprecated.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;ssh-mode&quot;&gt;SSH mode&lt;/h2&gt;

&lt;p&gt;The OpenSSH Agent protocol is always enabled (check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh&lt;/code&gt;), but &lt;em&gt;gpg-agent&lt;/em&gt; will only set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AUTH_SOCK&lt;/code&gt; variable if flag &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--enable-ssh-support&lt;/code&gt; is given.&lt;/p&gt;

&lt;p&gt;This mode does not require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AGENT_PID&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;gpg_agent_info&quot;&gt;GPG_AGENT_INFO&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;deprecated since GnuPG v2.1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Like SSH agent, GPG agent exports an environmental variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GPG_AGENT_INFO&lt;/code&gt; and file &lt;em&gt;~/.cache/gpg-agent-info&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnupg.org/gph/en/manual.html#AEN385&quot;&gt;web of trust&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/GnuPG#Using_a_GPG_agent&quot;&gt;gentoo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/GnuPG&quot;&gt;arch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/kensanata/ggg&quot;&gt;github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/chrisroos/1205934&quot;&gt;gpg-import-and-export-instructions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnupg.org/gph/en/manual/c481.html&quot;&gt;daily use of GnuPG&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>IME</title>
   <link href="/2016/01/01/ime/"/>
   <updated>2016-01-01T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2016/01/01/ime</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Emacs的chinese-pyim输入法已经越来越复杂，脱离了一个输入法插件的要求，不建议安装。Fcitx安装时去掉了默认的输入法（通过&lt;em&gt;-table&lt;/em&gt; USE）。额外安装fcitx-rime包。最好的用户词库工具是&lt;a href=&quot;https://github.com/studyzy/imewlconverter&quot;&gt;深蓝词库转换&lt;/a&gt;，支持几乎所有的主流输入法词库。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;＃ Fcitx基本概念&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;拼音文件 —— Pinyin File is a text file with pinyin and one character per line, separated with space (built-in &lt;em&gt;gbkpy.org&lt;/em&gt;).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;词库文件 —— Phrase File is a text file with full pinyin separated with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt; and the corresponding phrase (built-in &lt;em&gt;pyPhrase.org&lt;/em&gt;).&lt;/p&gt;

    &lt;p&gt;区分拼音文件和词库文件对于理解输入法非常重要。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Fcitx的安装不难。不过要用好的话，就应该设置好拼音文件文件和词库文件。&lt;/p&gt;

    &lt;p&gt;拼音文件基本不变。目前比较好的词库是来自搜狗拼音输入法，可以在官网免费下载 &lt;em&gt;*.scel&lt;/em&gt; 结尾的词库文件&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Fcitx和chinese-pyim无法直接使用搜狗拼音输入法的&lt;em&gt;*.scel&lt;/em&gt;词库文件，需要经过工具转换为中间格式&lt;em&gt;*.org&lt;/em&gt;格式。经过排序，去重后：&lt;/p&gt;

    &lt;p&gt;再将 &lt;em&gt;*.org&lt;/em&gt; 格式转换成Fcitx的二进制&lt;em&gt;*.mb&lt;/em&gt;格式；或转换成chinese-pyim的普通文本&lt;em&gt;*.pyim&lt;/em&gt;格式。&lt;em&gt;*.org&lt;/em&gt;格式既可以转成&lt;em&gt;chinese-pyim&lt;/em&gt;的&lt;em&gt;*.pyim&lt;/em&gt;格式，也可以转换成Fcitx的&lt;em&gt;*.mb&lt;/em&gt;格式。可以维护一份共同的&lt;em&gt;*.org&lt;/em&gt;中间格式词库文件。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在Linux上，所有的文件必需是UTF-8编码。用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enca/file test.org&lt;/code&gt;列出文件编码，用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enca -x UTF-8 test.org&lt;/code&gt;把文件转换成UTF-8编码。&lt;/p&gt;

    &lt;p&gt;如果编码非 UTF-8, 可能转换出错，即使转换成功，或者转换过程丢失很多词组。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;虽然chinese-pyim (参考Emacs configuration文）和Fcitx都可以用&lt;em&gt;*.org&lt;/em&gt;词库来转换，但有所不同：
    &lt;ol&gt;
      &lt;li&gt;Fcitx词库拼音分隔符是单引号&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt;，但是chinese-pyim则是除单引号&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt;之外的任何分隔符。&lt;/li&gt;
      &lt;li&gt;chinese-pyim需要合并相同拼音前缀的行，还需要去除同一行相同的候选词。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;fcitx词库设置&quot;&gt;Fcitx词库设置&lt;/h1&gt;

&lt;p&gt;Fcitx自带的拼音文件&lt;em&gt;gbkpy.org&lt;/em&gt;可以直接使用，但自带的词库文件&lt;em&gt;pyPhrase.org&lt;/em&gt;很差劲，根本没法用。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;参考&lt;a href=&quot;http://forum.ubuntu.org.cn/viewtopic.php?t=364764&quot;&gt;合并词库及方法步骤（2012-06-17 更新）&lt;/a&gt;和&lt;a href=&quot;http://forum.ubuntu.org.cn/viewtopic.php?t=252407&quot;&gt;120余万的搜狗细胞词库&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;去&lt;a href=&quot;http://pinyin.sogou.com/dict/&quot;&gt;搜狗词库官网&lt;/a&gt;下载各种词库文件。譬如放到&lt;em&gt;~/Downloads/scel/*.scel&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;把&lt;em&gt;*.scel&lt;/em&gt;文件转换成&lt;em&gt;*.org&lt;/em&gt;文件：&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;Downloads
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;org
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;scel
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;find &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-iname&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;*.scel&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; scel2org &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; ../org/&lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt;.org &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;i &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.scel&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;scel2org &lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; ../org/&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;.org&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ..
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls &lt;/span&gt;org
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;这个命来还会打印出所有被转换的词库名称。&lt;em&gt;~/Downloads/org/&lt;/em&gt;下存放着转换后的&lt;em&gt;*.scel.org&lt;/em&gt;文件，此文件是普通文本文件，可以用&lt;em&gt;less&lt;/em&gt;明令查看。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;合并所有的&lt;em&gt;*.scel.org&lt;/em&gt;文件为一个单一的&lt;em&gt;org&lt;/em&gt;文件。&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;dict
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;dict
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; ../org/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.scel.org &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 1.org
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;得到&lt;em&gt;1.org&lt;/em&gt;文件，合并词库文件，有利於提升输入法的性能。很明显从单个文件提词比从多个文件提词快。&lt;/p&gt;

    &lt;p&gt;到目前威治我们得了一个&lt;em&gt;*.org&lt;/em&gt;格式的大词库文件。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;从Fcitx源码包解压出&lt;em&gt;~/Downloads/dict/pyPhrase.org&lt;/em&gt; - Fcitx默认自带的词库文件，很糟糕，我们把它合并到刚刚生成的&lt;em&gt;1.org&lt;/em&gt;中。&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar &lt;/span&gt;xf fcitx-4.2.4.1_dict.tar.xz
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar &lt;/span&gt;xf fcitx-4.2.4.1_dict.tar.xz/data/pinyin.tar.gz
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar &lt;/span&gt;xf data/pinyin.tar.gz
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat &lt;/span&gt;pyPhrase.org &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; 1.org &lt;span class=&quot;c&quot;&gt;# 合并&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort &lt;/span&gt;1.org &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 2.org        &lt;span class=&quot;c&quot;&gt;# 排序&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;uniq &lt;/span&gt;2.org &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 3.org        &lt;span class=&quot;c&quot;&gt;# 去掉重复&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;转换成Fcitx使用的&lt;em&gt;*.mb&lt;/em&gt;格式。&lt;/p&gt;

    &lt;p&gt;从Fcitx源码包解压出&lt;em&gt;~/Downloads/dict/gbkpy.org&lt;/em&gt; - Fcitx默认自带的拼音文件，生成&lt;em&gt;*.mb&lt;/em&gt;词库需要拼音文件的辅助。&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp &lt;/span&gt;fcitx-4.2.4.1/data/gbkpy.org &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;man createPYMB
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;createPYMB gbkpy.org 3.org
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;如果 &lt;em&gt;3.org&lt;/em&gt; 文件非常大的话，可能需要10分钟左右，耐心等待。最后生成 4 个新文件:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dict/
├── 3.org
├── gbkpy.org
├── pyERROR   词库中重复或有问题的词条，有兴趣可参考，可以直接忽略
├── pyPhrase.ok 可以顺利转换的词条；和pyERROR一起就是3.org
├── pyphrase.mb 最终 Fcitx 使用的二进制词库，用它覆盖Fcitx原*pyphrase.mb*。
└── pybase.mb   二进制词库的配套字码库，用于覆盖原*pybase.mb*。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;只需要用新转换得到的&lt;em&gt;pybase.mb&lt;/em&gt;和&lt;em&gt;pyphrase.mb&lt;/em&gt;文件复盖原文件即可。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;复盖Fcitx原文件。&lt;/p&gt;

    &lt;p&gt;原文件一般位於系统路经 &lt;em&gt;/usr/share/fcitx/{data,pinyin}&lt;/em&gt; 和个人用户目录&lt;em&gt;~/.config/fcitx/{data,pinyin}&lt;/em&gt;。如果所在目录有原文件，就覆盖，没有的话就复制过去。&lt;/p&gt;

    &lt;p&gt;在我的Gentoo下，位於&lt;em&gt;{/usr/share,~/.config}/fcitx/pinyin/&lt;/em&gt;目录下。最后选择放到个人用户目录下。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;上面描述里从&lt;em&gt;*.scel&lt;/em&gt;到&lt;em&gt;*.org再到&lt;/em&gt;*. mb*格式的转换过程。&lt;/p&gt;

    &lt;p&gt;如果能从网上下载到比较好的&lt;em&gt;*.org&lt;/em&gt;或&lt;em&gt;*.mb&lt;/em&gt;会更省时（注意文件是否是UTF-8编码）。第四个参考链接里的&lt;em&gt;sougou-phrases-full.7z&lt;/em&gt;或&lt;em&gt;fcitx-sougou-phrase-full.7z&lt;/em&gt;不错。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;chinese-pyim词库设置&quot;&gt;chinese-pyim词库设置&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;上面得到的&lt;em&gt;3.org&lt;/em&gt;经过转换也可以给chinese-pyim使用。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;用&lt;em&gt;sed&lt;/em&gt;命令把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt;替换成&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt;：&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ibak&lt;/span&gt;  &lt;span class=&quot;s2&quot;&gt;&quot;s/&apos;/-/g&quot;&lt;/span&gt; 3.org
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;用&lt;em&gt;awk&lt;/em&gt;合并相同拼音前缀的行，也就是汉字的同音字/词。譬如&lt;em&gt;gai-shan 改善&lt;/em&gt;和&lt;em&gt;gai-shan 改删&lt;/em&gt;两行就需要合并成&lt;em&gt;gai-shan 改善 改删&lt;/em&gt;，这是chinese-pyim的要求，Fcitx并没有此要求。&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{key=$1; $1=&quot;&quot;; a[key]=a[key] $0}; END{ for (key in a) { print key a[key];}}&apos;&lt;/span&gt; 3.org &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 4.org
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;重新排序。经过&lt;em&gt;awk&lt;/em&gt;合并后，顺序打乱了：&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sort &lt;/span&gt;4.org &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; 5.pyim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在同一行去重复。譬如&lt;em&gt;a-ba 阿爸 阿坝 阿爸&lt;/em&gt;就需要去除多余的&lt;em&gt;阿爸&lt;/em&gt;，这是由于第三步合并时，可能有两行里包含相同的词。&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{printf(&quot;%s&quot;,$1); for (i=2;i&amp;lt;=NF;++i) if (!a[$1&quot; &quot;$i]++) printf(&quot; %s&quot;, $i); printf(&quot;\n&quot;);}&apos;&lt;/span&gt; 5.pyim &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; pyim-dict.pyim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;rime词库&quot;&gt;Rime词库&lt;/h1&gt;

&lt;p&gt;设置过程中参考&lt;a href=&quot;https://github.com/rime/home/wiki/CustomizationGuide&quot;&gt;Rime 定製指南&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;基本介绍&quot;&gt;基本介绍&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Rime比较好的地方是无广告、不联网、隐私高、定制性高。初期使用比较麻烦，好多概念不好理解。&lt;/li&gt;
  &lt;li&gt;添加用户自己的词库。&lt;/li&gt;
  &lt;li&gt;添加emoji输入。&lt;/li&gt;
  &lt;li&gt;同步用户定制。&lt;/li&gt;
  &lt;li&gt;Fcitx Rime配置文件&lt;em&gt;~/.config/fcitx/rime&lt;/em&gt;。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;windows&quot;&gt;Windows&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;最好在创建好多用户后，在普通帐户下安卓小狼毫。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;让多用户共享同一个用户文件夹。&lt;/p&gt;

    &lt;p&gt;虽然小狼毫自带的“小狼毫安装选项”可以更改用户文件夹，但是只对管理员账户有效。&lt;/p&gt;

    &lt;p&gt;打开注册表，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HKEY_CURRENT_USER\Software\Rime\Weasel&lt;/code&gt;里面有一个&lt;em&gt;string&lt;/em&gt;属性的&lt;em&gt;RimeUserDir&lt;/em&gt;参数（普通账户没有此参数要新新建一个），把它设置成新的用户文件夹地址（可能要重启），这样不同的Windows账户可以共用同一套配置。&lt;/p&gt;

    &lt;p&gt;一个更好的办法是从管理员账户注册表拷贝过来。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Windows和Linux没法共用一套配置，因为词库二进制格式不兼容。&lt;/li&gt;
  &lt;li&gt;Rime在Windows和Linux上不区分换行符，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\n&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\r\n&lt;/code&gt;都支持。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;简体配置&quot;&gt;简体配置&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Rime自带的5个默认输入方案，但是对与我来说，只需要使用其中的“朙月拼音·简化字”。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;每一个输入方案对应的配置文件以&lt;em&gt;.schema.yaml&lt;/em&gt;结尾。譬如“朙月拼音·简化字”对于的是&lt;em&gt;luna_pinyin_simp.schema.yaml&lt;/em&gt;。&lt;/p&gt;

    &lt;p&gt;由一个特殊的&lt;em&gt;default.yaml&lt;/em&gt;表示当前总配置，会随着用户其他配置的改变而改变。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;用什么输入方案就修改对应的配置文件。可以直接编辑默认&lt;em&gt;schema&lt;/em&gt;文件。但更好的方法是创建一个对应的&lt;em&gt;custom&lt;/em&gt;配置文件，如&lt;em&gt;default.custom.yaml&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;patch:
  menu/page_size: 9
  schema_list:
    - schema: luna_pinyin_simp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;patch&lt;/em&gt;表示对默认的配置&lt;em&gt;default.yaml&lt;/em&gt;进行修改。&lt;/li&gt;
      &lt;li&gt;候选项由5个词条改成9个。&lt;/li&gt;
      &lt;li&gt;输入方案去掉其他4个不需要的，只加载简体方案。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;让简体方案支持emoji表情输入。在&lt;em&gt;default.custom.yaml&lt;/em&gt; / &lt;em&gt;luna_pinyin_simp.custom.yaml&lt;/em&gt;加入：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;engine/translators:
  - punct_translator
  - r10n_translator
  - reverse_lookup_translator
recognizer/patterns/reverse_lookup: &quot;`[a-z]*$&quot;
schema/dependencies:
  - emoji
abc_segmentor/extra_tags:
  - reverse_lookup
reverse_lookup:
  dictionary: emoji
  enable_completion: false
  prefix: &quot;`&quot;
  tips: 〔表情〕
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;要输入表情，按&quot;`&quot;，后接对应的表情字符串，具体参考&lt;a href=&quot;https://github.com/rime/brise/blob/master/supplement/emoji.dict.yaml&quot;&gt;rime emoji&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;其中&lt;em&gt;abc_segmentor/extra_tags&lt;/em&gt;在输入汉字时，表情包也显示在候选项中，特别是输入单个字母时（如&apos;b&apos;)，候选项可能全是表情，可以注释掉。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;词库&quot;&gt;词库&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;词库文件分两种。
    &lt;ol&gt;
      &lt;li&gt;用户输入累计，文件名带&lt;em&gt;userdb&lt;/em&gt;。这个词库很小，基本不足为虑，可以随便编辑，甚至直接删除。&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;另一种就是我们要导入的大文本词库，文件名以&lt;em&gt;.dict.yaml&lt;/em&gt;结尾。导入后，通过点击「重新部署/deploy」生成二进制格式词典以&lt;em&gt;.table.bin&lt;/em&gt;结尾。&lt;/p&gt;

        &lt;p&gt;注意，重启Fcitx没有效果，必须「重新部署/deploy」。&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;文本词库&lt;em&gt;.dict.yaml&lt;/em&gt;的格式：&lt;/p&gt;

    &lt;p&gt;```&lt;/p&gt;
    &lt;h1 id=&quot;rime-dictionary&quot;&gt;Rime dictionary&lt;/h1&gt;
    &lt;h1 id=&quot;encoding-utf-8&quot;&gt;encoding: utf-8&lt;/h1&gt;
    &lt;p&gt;#&lt;/p&gt;
    &lt;h1 id=&quot;部署位置&quot;&gt;部署位置：&lt;/h1&gt;
    &lt;h1 id=&quot;configfcitxrime--linux&quot;&gt;~/.config/fcitx/rime  (Linux)&lt;/h1&gt;
    &lt;h1 id=&quot;configibusrime--linux&quot;&gt;~/.config/ibus/rime  (Linux)&lt;/h1&gt;
    &lt;h1 id=&quot;libraryrime--mac-os&quot;&gt;~/Library/Rime  (Mac OS)&lt;/h1&gt;
    &lt;h1 id=&quot;appdatarime--windows&quot;&gt;%APPDATA%\Rime  (Windows)&lt;/h1&gt;
    &lt;p&gt;#&lt;/p&gt;
    &lt;h1 id=&quot;于重新部署deploy后生效&quot;&gt;于「重新部署／deploy」后生效&lt;/h1&gt;
    &lt;p&gt;#&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;
&lt;p&gt;name: luna_pinyin_simp.zh-cn
   version: &quot;2016.03.02&quot;
   sort: by_weight
   use_preset_vocabulary: true
   import_tables:
     - luna_pinyin
   …&lt;/p&gt;

&lt;p&gt;啊啊	a a
   啊啊叫	a a jiao
   啊啊声	a a sheng
   啊哎	a ai
   阿巴	a ba
   阿爸	a ba
   阿坝	a ba&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
   1. 前面几行&apos;#&apos;表示注释。
   2. 三个连续的连接符&apos;-&apos;开始，后面紧跟文本词库的基本配置信息。

      *name*是词库名，词库名加上*.dict.yaml*后缀就是词库文件名。上面例子中，词库名是*luna_pinyin_simp.zh-cn*，对应的词库文件名是*luna_pinyin_simp.zh-cn.dict.yaml*。
   3. *import_tables* 表示导入其他词库。

      一个文本词库文件可以不需要后面的码表，直接导入多个已经存在的基本词库，这个和C语言里面的`#include &amp;lt;stdio.h&amp;gt;`类似。

      特别注意，*import_tables* 没法递归导入。被导入词库的码表部分会加到二进制词库里，开头部分信息（包括被导入词库的 *import_tables* 部分）。譬如 A 导入 B，B 导入了 C，但是最终生成的二进制 A 词库里只有 B 的码表内容，C 的码表内容并没有导入 A。正确的做法是 A 同时导入 B 和 C。
   4. 三个连续的&apos;.&apos;后面紧接词库码表。
   5. 上面码表的编码（拼音）可以省略，只剩字和词。因为在生成二进制词库时，Rime 库会依据输入方案的配置自动补齐编码（拼音）部分。

      这样，拼音方案、五笔方案、双拼方案可以公用同一个文本词库，Rime 会根据方案的命令自动补齐对应的编码（全拼码，五笔码，双拼码）。
3. 简体方案词库配置

   创建*luna_pinyin_simp.custom.yaml*:

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;patch:
     translator/dictionary: luna_pinyin_simp.zh-cn&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
   *translator/dictionary*表示这个方案使用的词库名。默认简体方案使用自带的*luna_pinyin*词库，现在修改成用户自己的*luna_pinyin_simp.zh-cn*。注意新词库包含了默认词库。
4. 设置同步

   同步用户配置以及词库本身，方便不同的机器共享。譬如可以同步到dropbox，这样不同的机器可以及时共享配置。

   直接編輯用戶文件夾下的*installation.yaml*，添加：

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;sync_dir: &quot;/home/username/workspace/rime&quot;
   installation_id: &quot;Rime&quot;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
   默认的*installation_id*是一串字母数字，改成比较好认识的。最终同步到 *sync_dir/installation_id* 下面。注意*sync_dir*必须是绝对路径，不要用tilde。

   同步分为两部分：

   1. 配置文件的同步是单向的，即有Rime目录同步到到*sync_dir*。所以在新机器上部署时，配置文件需要拷贝到Rime目录。
   2. 用户词库的同步是双向的，即在Rime目录和*sync_dir*之间双向同步。
5. 重新部署/deploy

   Fcitx的图像界面就有*deploy*字样，点击即可。如果找不到图形设置选项，可以：

   ```bash
   $ rm ~/.config/fcitx/rime/default.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后重启Fcitx。缺少&lt;em&gt;default.yaml&lt;/em&gt;，Rime会触发重新部署deploy。&lt;/p&gt;

&lt;p&gt;对于大的词库，可能需要等几分钟，Rime会根据文本词库生成对应的二进制词库&lt;em&gt;.table.bin&lt;/em&gt;。&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;同步概要
    &lt;ol&gt;
      &lt;li&gt;在Rime设置里点击“同步”。&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;因为Rime默认不会同步一些依赖的配置文件。所以第一次同步，还需要手动复制一些额外配置到同步目录下：&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; ~/.config/fcitx/rime/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.yaml sync_dir/installation_id
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;OpenCC&lt;/p&gt;

    &lt;p&gt;Fcitx 和 Fcitx-rime 都会依赖 &lt;em&gt;app-i18n/opencc&lt;/em&gt; 包。&lt;/p&gt;

    &lt;p&gt;简体繁体转换。&lt;em&gt;opencc&lt;/em&gt;命令默认是转换成繁体，如果是繁体转换成简体，则需要参数&lt;em&gt;-c&lt;/em&gt;，制定配置文件（&lt;em&gt;/usr/share/opencc/*.ini&lt;/em&gt;）。&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;opencc &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; input.file &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; output.file &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; /usr/share/opencc/zhs2zht.ini]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;重新部署&quot;&gt;重新部署&lt;/h2&gt;

&lt;p&gt;Rime把用户数据同步在&lt;em&gt;sync_dir&lt;/em&gt;下。当需要在新机器上安装Rime时，就可以利用备份快速部署。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;sync_dir&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ~/opt/rime-fcitx/Rime-Fcitx
default.custom.yaml
default.yaml
emoji.schema.yaml
installation.yaml
luna_pinyin.schema.yaml
luna_pinyin.userdb.txt
luna_pinyin_simp.big.dict.yaml
luna_pinyin_simp.custom.yaml
luna_pinyin_simp.fcitx.dict.yaml
luna_pinyin_simp.schema.yaml
luna_pinyin_simp.userdb.txt
symbols.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;备份数据主要有两种格式，一种是Rime配置文件&lt;em&gt;*.yaml&lt;/em&gt;，另一种是Rime根据用户日常输入习惯保存的小型词库&lt;em&gt;*.txt&lt;/em&gt;。需要注意的是，这种个人习惯词库一般称为“词典”比较合适，它和上面我们提到导入的大词库在格式、加载速度上大不同。用户习惯词典是文本文件，数据量很小，加载速度慢；&lt;em&gt;*.yaml&lt;/em&gt;词库在部署后会转成二进制&lt;em&gt;*.bin&lt;/em&gt;文件，加载到内存，查找速度快。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;导入配置文件&lt;/p&gt;

    &lt;p&gt;重点注意，虽然前面备份时，额外拷贝了诸如&lt;em&gt;default.yaml&lt;/em&gt;之类的文件，但是导入时最好重新用官方的。因为拷贝的&lt;em&gt;default.yaml&lt;/em&gt;可能含有多余的选项。&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; ~/opt/rime-fcitx/Rime-Fcitx/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.yaml ~/.config/fcitx/rime
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;前面说过，配置文件的同步是单向的，所以必须拷贝。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;重新部署&lt;/li&gt;
  &lt;li&gt;同步词典
    &lt;ol&gt;
      &lt;li&gt;导入用户词典之前必须关闭Rime输入法，因为Rime运行时独享对用户习惯词典写权限。&lt;/li&gt;
      &lt;li&gt;必须在Rime目录下运行。&lt;/li&gt;
    &lt;/ol&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/.config/fcitx/rime
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rime_dict_manager
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rime_dict_manager &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rime_dict_manager &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; luna_pinyin_simp  ~/opt/rime-fcitx/Rime-Fcitx/luna_pinyin_simp.userdb.txt
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;rime_dict_manager &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;启动Rime即可。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ref&quot;&gt;Ref&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://forum.ubuntu.org.cn/viewtopic.php?t=364764&quot;&gt;合并词库及方法步骤（2012-06-17 更新）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://forum.ubuntu.org.cn/viewtopic.php?t=252407&quot;&gt;120余万的搜狗细胞词库&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Fcitx_%28简体中文%29&quot;&gt;fcitx archlinux&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://code.google.com/p/hslinuxextra/downloads/list&quot;&gt;词库下载&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://tieba.baidu.com/p/4125987751&quot;&gt;rime词库&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Java</title>
   <link href="/2015/12/15/jdk/"/>
   <updated>2015-12-15T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/12/15/jdk</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#abcs&quot; id=&quot;markdown-toc-abcs&quot;&gt;ABCs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#icedtea-open-java-se&quot; id=&quot;markdown-toc-icedtea-open-java-se&quot;&gt;IcedTea Open Java SE&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#oracles-java-se&quot; id=&quot;markdown-toc-oracles-java-se&quot;&gt;Oracle&apos;s Java SE&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configuring&quot; id=&quot;markdown-toc-configuring&quot;&gt;Configuring&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#practice&quot; id=&quot;markdown-toc-practice&quot;&gt;Practice&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#bugs&quot; id=&quot;markdown-toc-bugs&quot;&gt;Bugs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#refs&quot; id=&quot;markdown-toc-refs&quot;&gt;Refs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;There are three different editions of the Java platform: Standard Edition (SE), Enterprise Edition (EE), and Micro Edition (ME).&lt;/p&gt;

    &lt;p&gt;Most of the time, we require the SE version. Currently, version 7 is most widely deployed.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are two different Java implementations: OpenJDK and Oracle Java.&lt;/p&gt;

    &lt;p&gt;They mostly depends on the same code but OpenJDK is fully open source while Oracle Java contains some proprietary binaries. Most Java applications work fine with either implementation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are two different Java packages: JDK and JRE.&lt;/p&gt;

    &lt;p&gt;Java Development Kit (JDK) for Java development (programming) while Java Runtime Environment (JRE) to run Java application. JDK includes JRE. So when installing JDK, there is no need to install JRE any more.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Java Distributions.&lt;/p&gt;

    &lt;p&gt;IcedTea Open Java SE, Sun&apos;s Java 6 SE, Oracle&apos;s Java 7/8 SE, IBM Java SE, etc.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Oracle&apos;s Java is previously called Sun Java (&amp;lt;= version 6) that was acquisited by Oracle, Inc.&lt;/li&gt;
      &lt;li&gt;IcedTea can be consireded a &lt;em&gt;distribution&lt;/em&gt; of OpenJDK. In most GNU/Linux systems, OpenJDK is released as IcedTea, though the release is still named as OpenJDK.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Oracle&apos;s Java 8 SE is released at the time of writing this post but some new features make it incompatible with priori versions.&lt;/p&gt;

    &lt;p&gt;However, Oracle&apos;s Java 7 SE is vulnerable in spite of its efforts to release patches. If you really like Oracle&apos;s Java, use version 8 instead!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;icedtea-open-java-se&quot;&gt;IcedTea Open Java SE&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# emerge -pvt virtual/jdk&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# emerge -pvt virtual/jre&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;oracles-java-se&quot;&gt;Oracle&apos;s Java SE&lt;/h1&gt;

&lt;p&gt;Though Oracle Java SE is unfavorable, this section just shows how to install  &lt;em&gt;restrictive&lt;/em&gt; packages.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Oracle Java SE is a &lt;em&gt;fetch-restricted&lt;/em&gt; package, thus need a few extra steps to &lt;em&gt;emerge&lt;/em&gt;. For instance, we should manually download the &lt;em&gt;distfile&lt;/em&gt; at first. Try:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# emerge -pvt oracle-jdk-bin:1.7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Slot 1.7 means Java 7 while 1.8 refers to Java 8. Likely:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;These are the packages that would be merged, in reverse order:

Calculating dependencies... done!
[ebuild  N F   ] dev-java/oracle-jdk-bin-1.7.0.80:1.7::gentoo  USE=&quot;X alsa fontconfig (-aqua) -derby -doc -examples -jce -nsplugin -pax_kernel (-selinux) -source&quot; 149,933 KiB
[ebuild  N     ]  dev-java/java-config-2.2.0:2::gentoo  PYTHON_TARGETS=&quot;python2_7 python3_4 -python3_3&quot; 51 KiB
[ebuild  N     ]   dev-java/java-config-wrapper-0.16::gentoo  8 KiB
[ebuild  N     ]   sys-apps/baselayout-java-0.1.0::gentoo  71 KiB
[ebuild  N     ]  app-eselect/eselect-java-0.1.0::gentoo  71 KiB

Total: 5 packages (5 new), Size of downloads: 150,132 KiB
Fetch Restriction: 1 package (1 unsatisfied)

Fetch instructions for dev-java/oracle-jdk-bin-1.7.0.80:
 * 
 * Oracle requires you to download the needed files manually after
 * accepting their license through a javascript capable web browser.
 * 
 * Download the following files:
 *   jdk-7u80-linux-x64.tar.gz
 * at &apos;http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html#jdk-7u80-oth-JPR&apos;
 * and move them to &apos;/usr/portage/distfiles&apos;
 * 
 * If the above mentioned urls do not point to the correct version anymore,
 * please download the files from Oracle&apos;s java download archive:
 * 
 *    http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase7-521261.html#jdk-7u80-oth-JPR
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Go to the specified URL of &lt;em&gt;ebuild&lt;/em&gt;, download &lt;em&gt;jdk-7u80-linux-x64.tar.gz&lt;/em&gt; and put it under &lt;em&gt;/usr/portage/distfiles&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Accept the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Oracle-BCLA-JavaSE&lt;/code&gt; license.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/portage/package.license/oracle-jdk-bin
# required by oracle-jdk-bin (argument)
dev-java/oracle-jdk-bin:1.7 Oracle-BCLA-JavaSE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Emerge&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# emerge -av oracle-jdk-bin:1.7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Notes&lt;/p&gt;

    &lt;p&gt;Don&apos;t add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsplugin&lt;/code&gt; USE flag. Java plugin is now almost dead and vulnerable when browsing the Internet.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;configuring&quot;&gt;Configuring&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;A package &lt;em&gt;java-config&lt;/em&gt; is installed alongside the JDK, which serves the same goal as Gentoo&apos;s &lt;em&gt;eselect java-vm&lt;/em&gt; utility to choose JDK slots.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Using the &lt;em&gt;java-config&lt;/em&gt; / &lt;em&gt;eselect&lt;/em&gt; tool with root privileges, a system-wide default java virtual machine (VM) can be set. Of course, you can also use &lt;em&gt;java-config&lt;/em&gt; / &lt;em&gt;eselect&lt;/em&gt; to customize their personal VM on a user-by-user basis.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;java-config &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
java-config &lt;span class=&quot;nt&quot;&gt;-L&lt;/span&gt;
java-config &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; | &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; vm
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
eselect java-vm &lt;span class=&quot;nb&quot;&gt;help
&lt;/span&gt;eselect java-vm list
eselect java-vm show
eselect java-vm &lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; system | user] vm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAVA_HOME&lt;/code&gt; etc. environment variables is set automatically by &lt;em&gt;/etc/profile.d/java-config-2.sh&lt;/em&gt; script from the &lt;em&gt;ebuild&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;practice&quot;&gt;Practice&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;You can install the Oracle 8 alongside IcedTea 7.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Set system-vm to IcedTea 7 while set normal user-vm to Oracle 8.  IcedTea 7 is stable and widely compatible while Oracle 8 assumes new Java features.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;eselect java-vm list
Available Java Virtual Machines:
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;1]   icedtea-bin-7  system-vm
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2]   oracle-jdk-bin-1.8  user-vm
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;eselect java-vm &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;user 2
&lt;span class=&quot;c&quot;&gt;# eselect java-vm set system 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Note: you cannot set user-vm under root account (root uses system-vm).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;bugs&quot;&gt;Bugs&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;dev-java/icedtea-bin:8&lt;/em&gt; &lt;a href=&quot;https://github.com/JesusFreke/smali/issues/514&quot;&gt;throws SSL error&lt;/a&gt; when running gradlew:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Exception in thread &quot;main&quot; javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://bugzilla.redhat.com/show_bug.cgi?id=1417317&quot;&gt;redhat bug 1417317&lt;/a&gt; and &lt;a href=&quot;https://bugs.gentoo.org/show_bug.cgi?id=605430&quot;&gt;gentoo bug 605430&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Currently, upgrading to &lt;em&gt;dev-java/icedtea-bin-3.3.0-r1:8&lt;/em&gt; fixes the issue.&lt;/p&gt;

&lt;h1 id=&quot;refs&quot;&gt;Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Java&quot;&gt;gentoo wiki java&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Project:Java/User_Guide&quot;&gt;gentoo java guide&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>IRC</title>
   <link href="/2015/10/10/irc/"/>
   <updated>2015-10-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/10/10/irc</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#abcs&quot; id=&quot;markdown-toc-abcs&quot;&gt;ABCs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#style&quot; id=&quot;markdown-toc-style&quot;&gt;Style&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#security&quot; id=&quot;markdown-toc-security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#server_default&quot; id=&quot;markdown-toc-server_default&quot;&gt;server_default&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#server&quot; id=&quot;markdown-toc-server&quot;&gt;Server&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#nickserv&quot; id=&quot;markdown-toc-nickserv&quot;&gt;NickServ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#identification&quot; id=&quot;markdown-toc-identification&quot;&gt;Identification&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#manually-identification&quot; id=&quot;markdown-toc-manually-identification&quot;&gt;Manually Identification&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#sasl-plain-scheme&quot; id=&quot;markdown-toc-sasl-plain-scheme&quot;&gt;SASL plain scheme&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#sasl-external-scheme&quot; id=&quot;markdown-toc-sasl-external-scheme&quot;&gt;SASL external scheme&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#ircpem&quot; id=&quot;markdown-toc-ircpem&quot;&gt;irc.pem&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#nick-and-certificate-association&quot; id=&quot;markdown-toc-nick-and-certificate-association&quot;&gt;Nick and Certificate Association&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#renew-certificate&quot; id=&quot;markdown-toc-renew-certificate&quot;&gt;Renew certificate&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#unaffilicated-cloak&quot; id=&quot;markdown-toc-unaffilicated-cloak&quot;&gt;Unaffilicated Cloak&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#proxy---tor&quot; id=&quot;markdown-toc-proxy---tor&quot;&gt;proxy - Tor&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#relay&quot; id=&quot;markdown-toc-relay&quot;&gt;Relay&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#weechat-relay&quot; id=&quot;markdown-toc-weechat-relay&quot;&gt;Weechat Relay&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#nginx-reverse-proxy&quot; id=&quot;markdown-toc-nginx-reverse-proxy&quot;&gt;Nginx Reverse Proxy&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#direct-relay&quot; id=&quot;markdown-toc-direct-relay&quot;&gt;Direct Relay&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#connect-to-relay&quot; id=&quot;markdown-toc-connect-to-relay&quot;&gt;Connect to Relay&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#systemd-user-unit&quot; id=&quot;markdown-toc-systemd-user-unit&quot;&gt;Systemd user Unit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#troubleshooting&quot; id=&quot;markdown-toc-troubleshooting&quot;&gt;Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;Simple Authentication and Security Layer (SASL) is a method that simplify identification to NickServ as the first step after connecting to IRC servers, before anything else happens. To connect to freenode using Tor, SASL is required. In this post, I will take Weechat and Freenode for example.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Conncet through WebChat on browser.&lt;/p&gt;

    &lt;p&gt;Just fill in nick and channel names on &lt;a href=&quot;https://webchat.freenode.net&quot;&gt;freenode webchat&lt;/a&gt;. HTTPS (ssl) establish a secure connection IRC server compared to HTTP.&lt;/p&gt;

    &lt;p&gt;By Webchat, we cannot require other services.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Connect in the clear.&lt;/p&gt;

    &lt;p&gt;Similar to Webchat, the clear way connects directly without proxy or nick reservation (by NickServ).&lt;/p&gt;

    &lt;p&gt;Should provide IRC hostname (&lt;em&gt;chat.freenode.net&lt;/em&gt;) and port (6697) which are implicit in Webchat (&lt;em&gt;webchat.freenode.net&lt;/em&gt; and 80).&lt;/p&gt;

    &lt;p&gt;After connection, join a channel to talk.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Connect through Clients (Weechat Irssi etc.).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Nickserv - register/identify&lt;/p&gt;

    &lt;p&gt;Reserve and identify your nick name.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SASL authentication&lt;/p&gt;

    &lt;p&gt;Automatic identification on connection by SASL. Weechat SASL supports different authentication mechanisms:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;plain: plain text file password (default)&lt;/li&gt;
      &lt;li&gt;ecdsa-nist256p-challenge: challenge with public/private key&lt;/li&gt;
      &lt;li&gt;external: self-signed SSL certificate&lt;/li&gt;
      &lt;li&gt;…&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Connect with proxy (i.e. Tor).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Bounce_%28network%29&quot;&gt;BNC&lt;/a&gt; (i.e. ZNC), or Weechat relay protocol.&lt;/p&gt;

    &lt;p&gt;Weechat relay supports IRC protocol as well (to be compatibile with other IRC clients).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;style&quot;&gt;Style&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@laptop ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;weechat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;iset&lt;/em&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/script search iset
Alt + i
/save
/iset
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;/save&lt;/em&gt; after changes. WeeChat also saves your up-to-date configuration any time you exit the program.&lt;/p&gt;

    &lt;p&gt;Script &lt;em&gt;iset&lt;/em&gt; is decpreated and please use built-in script &lt;em&gt;fset&lt;/em&gt; instead.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Some specific server commands (i.e. &lt;em&gt;/ns&lt;/em&gt;) are not standard and cannot be recoginized by IRC client.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irc.network.send_unknown_commands on
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;This will close the &lt;em&gt;buffer&lt;/em&gt; (or called &lt;em&gt;tab&lt;/em&gt;) immediately when &lt;em&gt;part&lt;/em&gt;ing a channel.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irc.look.part_closes_buffer on
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;By default, &lt;em&gt;server&lt;/em&gt; and &lt;em&gt;core&lt;/em&gt; buffers are merged together. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+x&lt;/code&gt; to tear apart or:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irc.look.server_buffer independent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;security&quot;&gt;Security&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;SSL&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irc.server_default.ssl on
irc.server_default.ssl_verify on
irc.server_default.sasl_mechanism external
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The client verify the server certificate and also the server needs to verify the client certificate - mutual authentication!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Turn off &lt;em&gt;ctcp&lt;/em&gt; to prevent others from querying IRC client information.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;*ctcp*  &quot;&quot;
*ctcp* off
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Message&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irc.server_default.msg_part &quot;&quot;
irc.server_default.msg_quit &quot;&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;server_default&quot;&gt;server_default&lt;/h1&gt;

&lt;p&gt;Some extra optional default server arguments.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irc.server_default.nicks &quot;&quot;
irc.server_default.username &quot;&quot;
irc.server_default.realname &quot;&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;server&quot;&gt;Server&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/server add freenode chat.freenode.net/6697 -ssl
/set irc.server.freenode.nicks &quot;username&quot;
/connect freenode
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Check &lt;em&gt;server_default&lt;/em&gt; section of &lt;em&gt;~/.config/weechat/irc.conf&lt;/em&gt;. Common default server options can be set here (i.e. &lt;em&gt;irc.server_default.ssl&lt;/em&gt;).&lt;/p&gt;

&lt;h1 id=&quot;nickserv&quot;&gt;NickServ&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;NickServ&lt;/em&gt; allows users to register nicks on IRC servers. Different IRC servers support different set of NickServ commands. We can check by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/msg nickserv help&lt;/code&gt; beforehand. Make sure you are connected to IRC server with your desired nick by &lt;em&gt;/nick new-nick&lt;/em&gt; command.&lt;/p&gt;

&lt;p&gt;Don&apos;t execute the following commands in a channel tab, otherwise sensitive information (i.e. password) might be disposed and sniffed. All IRC commands are case-insensitive.&lt;/p&gt;

&lt;p&gt;Take Freenode for example:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/msg NickServ REGISTER &amp;lt;password&amp;gt; youremail@example.com&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;In Weechat, the &lt;em&gt;pasword youremail@example.com&lt;/em&gt; part will be displayed as asterisks. But don&apos;t worry as long as you put a space between &lt;em&gt;password&lt;/em&gt; and &lt;em&gt;youremail@example.com&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;After this command, Weechat will show &lt;em&gt;password&lt;/em&gt; and &lt;em&gt;youremail@example.com&lt;/em&gt; as plain text. IRC server uses the current nick (&lt;em&gt;username&lt;/em&gt;) as the account name. So &lt;em&gt;username&lt;/em&gt; is both the nick and account name registered on &lt;em&gt;freenode&lt;/em&gt;. This special nick is called &lt;em&gt;primary nick&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;In a while, you will receive an email, from which you should copy the verification command to complete the registration process:&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/msg nickserv confirm &amp;lt;temporary-code&amp;gt;&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/msg nickserv verify register &amp;lt;username&amp;gt; &amp;lt;temporary-code&amp;gt;&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;This &lt;em&gt;temporary-code&lt;/em&gt; is only for account registration confirm.&lt;/p&gt;

    &lt;p&gt;Now, account name &lt;em&gt;username&lt;/em&gt; has just one nick &lt;em&gt;username&lt;/em&gt; associated on Freenode server, no one else can use nick &lt;em&gt;username&lt;/em&gt; unless the correct &lt;em&gt;password&lt;/em&gt; is identified (talked later on).&lt;/p&gt;

    &lt;p&gt;OFTC server does need this extra confirmation step.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/msg NickServ SET HIDE EMAIL ON&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;To keep your email address private, rather than displaying it publicly, mark it as hidden.&lt;/p&gt;

    &lt;p&gt;For OFTC, it&apos;s &lt;em&gt;/msg nickserv set private on&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Group more nicks account.&lt;/p&gt;

    &lt;p&gt;A Freenode account can reserve multiple nicks. First switch to a new nick and then &lt;em&gt;group&lt;/em&gt; it to our account (as long as that nick is not reserved by others). Grouping nicks in this way gives you the benefit of having all your nicks covered by the same &lt;a href=&quot;#unaffiliated-cloak&quot;&gt;unaffiliated cloak&lt;/a&gt;. The default group name is the account name, namely &lt;em&gt;username&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# switch to nick &quot;username_&quot;
/nick username_
    
/msg nickserv group
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;To remove a nick from your account:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/nick username
/msg nickserv ungroup username_
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/reconnect&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;It will prompt like &lt;em&gt;username is registered… you must identify yourself…&lt;/em&gt;. To identify yourself as nick &lt;em&gt;username&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/msg NickServ identify username &amp;lt;password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;identification&quot;&gt;Identification&lt;/h1&gt;

&lt;h2 id=&quot;manually-identification&quot;&gt;Manually Identification&lt;/h2&gt;

&lt;p&gt;If you don&apos;t configure SASL, then you have two choices:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Manual identification after connection to server as above.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/reconnect freenode
   
/msg NickServ identify username &amp;lt;password&amp;gt; # freenode
/msg NickServ identify &amp;lt;password&amp;gt; username # oftc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use &lt;em&gt;freenode.command&lt;/em&gt; to run &lt;em&gt;identify&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irc.server.freenode.command &quot;/msg NickServ identify username &amp;lt;password&amp;gt;&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;freenode.command&lt;/em&gt; runs a command automatically once connected to the server.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;sasl-plain-scheme&quot;&gt;SASL plain scheme&lt;/h2&gt;

&lt;p&gt;OFTC disallow this scheme.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irc.server.freenode.sasl_mechanism plain&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;set irc.server.freenode.sasl_username username&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;The username can be any one of your grouped nicks. But usually the primary nick (namely the account name) is used.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/secure set freenode &amp;lt;password&amp;gt;&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;Password will be recorded in &lt;em&gt;~/.config/weechat/sec.conf&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irc.server.freenode.sasl_password &quot;${sec.data.freenode}&quot;&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;Tell &lt;em&gt;weechat&lt;/em&gt; where to get the password.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irc.server.freenode.sasl_fail disconnect&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;If SASL auth fail, disconnect.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;sasl-external-scheme&quot;&gt;SASL external scheme&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irc.server.freenode.sasl_mechanism external&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;As long as &lt;em&gt;sasl_mechanism&lt;/em&gt; is changed to &lt;em&gt;external&lt;/em&gt;, &lt;em&gt;sasl_username&lt;/em&gt; and &lt;em&gt;sasl_password&lt;/em&gt; setting won&apos;t take effect.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irc.server.freenode.ssl_cert &quot;%h/ssl/freenode.pem&quot;&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;We should generate a self-signed X509 certificate before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/reconnect&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;ircpem&quot;&gt;irc.pem&lt;/h3&gt;

&lt;p&gt;OpenSSL is a cryptography toolkit implementing the SSL/TLS protocols and related cryptography libraries. Virtually, almost any packages using SSL/TLS require OpenSSL support, OpenSSH and Firefox (HTTPS) included.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;openssl&lt;/em&gt; program is a command line tool from OpenSSL, providing various cryptography functions. In this post, it will used to genrate self-signed X509 certificate.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@laptop ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;openssl req &lt;span class=&quot;nt&quot;&gt;-newkey&lt;/span&gt; rsa:4096 &lt;span class=&quot;nt&quot;&gt;-nodes&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-keyout&lt;/span&gt; irc.pem &lt;span class=&quot;nt&quot;&gt;-sha256&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-x509&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-days&lt;/span&gt; 365 &lt;span class=&quot;nt&quot;&gt;-out&lt;/span&gt; irc.pem &lt;span class=&quot;nt&quot;&gt;-subj&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/C=US/ST=NewYork/L=NewYork/O=UST/OU=CS/CN=irc&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-addext&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;subjectAltName = DNS:irc, DNS:weechat, DNS:127.0.0.1&quot;&lt;/span&gt;
jim@laptop ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/.config/weechat/ssl
jim@laptop ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mv &lt;/span&gt;irc.pem ~/.config/weechat/ssl/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;req: certificate request and certificate generating utility.&lt;/li&gt;
  &lt;li&gt;nodes: no DES encryption. The RSA private key won&apos;t be encrypted by DES.&lt;/li&gt;
  &lt;li&gt;keyout: the private key file.&lt;/li&gt;
  &lt;li&gt;sha256: the digest to sign certificate.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;out: the certificate file.&lt;/p&gt;

    &lt;p&gt;The &lt;em&gt;keyout&lt;/em&gt; and &lt;em&gt;out&lt;/em&gt; specify the same output file name, which means private key and certificate will be merged automatically.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;subj: certificate Subject field. If not provided on command line, &lt;em&gt;openssl&lt;/em&gt; will prompt for user input.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;nick-and-certificate-association&quot;&gt;Nick and Certificate Association&lt;/h3&gt;

&lt;p&gt;To achieve certificate authentication, we should add the certificate&apos;s fingerprint to NickServ on freenode server&lt;/p&gt;

&lt;p&gt;Get the SHA512 fingerprint.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jim@laptop ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;man x509
jim@laptop ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;openssl x509 &lt;span class=&quot;nt&quot;&gt;-noout&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-text&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sha512&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-fingerprint&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; irc.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add the fingerprint:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/whois nick
/msg nickserv cert list
/msg nickserv cert add/del [sha1]

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

&lt;p&gt;The fingerprint value can be ommited and NickServ on the server will automatically calculate the value.&lt;/p&gt;

&lt;p&gt;Finally reconnect to identify nick by SASL external. You can see a line:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;gnutls: sending one certificate&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;during connection. Run &lt;em&gt;/whois nick&lt;/em&gt; to see:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;has client certificate fingerprint: &lt;your fingerprint=&quot;&quot; here=&quot;&quot;&gt;&lt;/your&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;renew-certificate&quot;&gt;Renew certificate&lt;/h3&gt;

&lt;p&gt;Upon expiration, we need to renew the certificate. Acutally, renewing is to create a new certificate herein.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Extract private key from certification file (PEM)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# openssl rsa -in irc.pem -out irc.key&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Extract public certificate from certification file (PEM)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# openssl x509 -in irc.pem -out irc.crt&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Converts the certificate into a certificate request (PEM)&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# openssl x509 -x509toreq -in irc.crt -out irc.csr -signkey irc.key&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Create a new certification for one year&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# openssl x509 -req -days 365 -in irc.csr -out irc.crt.new -signkey irc.key&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Concatenate the new certificate and original key&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# cat irc.crt.new irc.key &amp;gt; irc.pem.new&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Chceck validity&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# openssl x509 -noout -text -in irc.pem.new&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remember to add the new certificate&apos;s fingerprint to IRC server and del the old one.&lt;/p&gt;

&lt;h1 id=&quot;unaffilicated-cloak&quot;&gt;Unaffilicated Cloak&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Unaffiliated Cloak is to hide your IP from IRC channels.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To obtain a cloak, just join the official &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#freenode&lt;/code&gt; channel, ask for one there and reconnect.&lt;/p&gt;

    &lt;p&gt;When channel staff notices your request, you &lt;em&gt;might&lt;/em&gt; get cloaked. Unaffiliated Cloak applies to all channels on Freenode server.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To get a cloak on OFTC is much easier:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/msg nickserv SET CLOAK ON
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The above method is now deprecated! Freenode automatically turns on cloak (vHost) for every account. Just run command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/msg HOSTSERV ON&lt;/code&gt;. Checking by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/whois &amp;lt;username&amp;gt;&lt;/code&gt;. Before and after:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# before
(~weechat@joseon-eldv4c.jnih.mqbr.vquou2.IP): weechat
# after
(~weechat@joseon/user/username): weechat
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;proxy---tor&quot;&gt;proxy - Tor&lt;/h1&gt;

&lt;p&gt;Suppose you would like to connect to IRC server by proxy, how to set?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Add proxy&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/proxy add tor socks5 127.0.0.1 9050
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This will tell Weechat that a proxy named &apos;tor&apos; is added.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Server copy&lt;/p&gt;

    &lt;p&gt;Suppose we find Tor proxy is troublesome someday, updates to current server must be restored. To ease configuration, issue the following command:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/server copy freenode freenode-tor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Update &lt;em&gt;freenode-tor&lt;/em&gt; configuration instead.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable proxy for IRC server&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/set irc.server.freenode-tor.proxy tor
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;However Freenode does not allow Tor connection to &lt;em&gt;chat.freenode.net&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;The server hostname should be changed to hidden url &lt;em&gt;freenodeok2gncmy.onion&lt;/em&gt; while keeping the original port.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/set irc.server.freenode-tor.addresses freenodeok2gncmy.onion/6697
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Onion certificate.&lt;/p&gt;

    &lt;p&gt;Cannot wait to reconnect? Yeah, me too. The server certificate cannot be verified since onion url is not certified by almost all CAs.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;gnutls: the hostname in the certificate does NOT match &quot;freenodeok2gncmy.onion&quot;&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Currently, only a few onion url is signed by &lt;a href=&quot;https://www.digicert.com&quot;&gt;digicert&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;The solution is maully trust fetched certificates in which though the hostname is &lt;em&gt;freenode.net&lt;/em&gt; instead of &lt;em&gt;freenodeok2gncmy.onion&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;When connected to &lt;em&gt;chat.freenode.net&lt;/em&gt;, Weechat usually receive three certificates with their SHA-1 fingerprints listed. Collect those fingerprints and assign to:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/set irc.server.freenode-tor.ssl_fingerprint fp1,fp2,fp3,...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Alternatively we can turn off certificate verification:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/set irc.server.freenode-tor.ssl_verify off
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If IRC client supports &lt;a href=&quot;https://freenode.net/kb/answer/chat&quot;&gt;&lt;strong&gt;key pinning&lt;/strong&gt;&lt;/a&gt;, we can choose to trust freenode&apos;s public key fingerprint instead certificate&apos;s fingerprint which benefits us in that the former keep consistent while the later varies in accord with the real freenode server you connect to. Unfortunately, Weechat does not.&lt;/p&gt;

    &lt;p&gt;If Weechat throws errors like:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;gnutls: peer&apos;s certificate is NOT trusted&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;blockquote&gt;
      &lt;p&gt;gnutls: peer&apos;s certificate issuer is unknown&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Please check &lt;a href=&quot;https://github.com/weechat/weechat/issues/972&quot;&gt;whether&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;weechat.network.gnutls_ca_file&lt;/code&gt; is correctly set. On Centos, it should be &lt;em&gt;/etc/pki/tls/certs/ca-bundle.crt&lt;/em&gt;; but on archlinux, it should be &lt;em&gt;/etc/ssl/certs/ca-certificates.crt&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Recently, freenode Tor servers do not report certificate fingerprint anymore. We can manually print fingerprint by:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;torify gnutls-cli &lt;span class=&quot;nt&quot;&gt;--tofu&lt;/span&gt; freenodeok2gncmy.onion:6697  &lt;span class=&quot;nt&quot;&gt;--print-cert&lt;/span&gt; | openssl x509 &lt;span class=&quot;nt&quot;&gt;-noout&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-text&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sha256&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-fingerprint&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-in&lt;/span&gt; /dev/stdin
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/://g&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;fingerprint delimited by colons&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;relay&quot;&gt;Relay&lt;/h1&gt;

&lt;p&gt;To preserve or share IRC message, we can use Bounced Network Connection (BNC) like &lt;a href=&quot;http://wiki.znc.in/ZNC&quot;&gt;ZNC&lt;/a&gt;. ZNC allows connections from different end users and relay message for each of them.&lt;/p&gt;

&lt;p&gt;To simplify the setup, we can use the standard IRC relay and its extended version - &lt;em&gt;weechat relay&lt;/em&gt;. Weechat supports both the &lt;em&gt;weechat relay&lt;/em&gt; and the standard IRC relay.&lt;/p&gt;

&lt;p&gt;If you add a standard IRC relay in Weechat, you can connect to it with any IRC client like HexChat, Irssi etc. The &lt;em&gt;weechat relay&lt;/em&gt; runs over Websocket and only allows connections from clients that support Websocket like &lt;em&gt;glowing-bear&lt;/em&gt; or &lt;a href=&quot;https://github.com/ubergeek42/weechat-android&quot;&gt;Weechat android&lt;/a&gt;. However, you can &lt;strong&gt;not&lt;/strong&gt; connect to a weechat relay by weechat installed from Linux package manager!&lt;/p&gt;

&lt;p&gt;This section demonstrates &lt;a href=&quot;https://rigtorp.se/notes/weechat/&quot;&gt;the following schema&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Create a &lt;em&gt;weechat relay&lt;/em&gt; instance on a remote server, bound to loopback.&lt;/li&gt;
  &lt;li&gt;Nginx as a reverse proxy.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://latest.glowing-bear.org/&quot;&gt;Glowing-bear&lt;/a&gt; or Weechat-android as the front-end client.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;weechat-relay&quot;&gt;Weechat Relay&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Add relay&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/relay add ipv4.weechat 9000  # plaintext relay without SSL
/set relay.network.bind_address &quot;127.0.0.1&quot;
/set relay.network.password MY-RELAY-PASSWORD
/set relay.network.max_clients 3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;nginx-reverse-proxy&quot;&gt;Nginx Reverse Proxy&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Nginx HTTPS sample&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;server {
    listen 80;
    ...
    # enforce https
    return 301 https://$server_name$request_uri;
}

server  {
    ...
    ssl_certificate &quot;/etc/letsencrypt/live/irc.example.com/fullchain.pem&quot;;
    ssl_certificate_key &quot;/etc/letsencrypt/live/irc.example.com/privkey.pem&quot;;
    ....
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add nginx proxy&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Set connection header based on upgrade header
map $http_upgrade $connection_upgrade {
    default upgrade;
    &apos;&apos; close;
}

# Protect from brute force attack
limit_req_zone $binary_remote_addr zone=weechat:10m rate=5r/m;

server {
    listen 80;
    server_name irc.example.com;

    return 301 https://$server_name$request_uri;

}

server {
    listen 443 ssl http2;
    server_name cloud.example.com;

    ssl_certificate &quot;/etc/letsencrypt/live/irc.example.com/fullchain.pem&quot;;
    ssl_certificate_key &quot;/etc/letsencrypt/live/irc.example.com/privkey.pem&quot;;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout 10m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
	   
    location /weechat {
         proxy_pass http://127.0.0.1:12545;
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection $connection_header;
         proxy_set_header Host $http_host;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_read_timeout 3600;
         limit_req zone=weechat burst=1 nodelay;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;direct-relay&quot;&gt;Direct Relay&lt;/h2&gt;

&lt;p&gt;Acutally, we can connect to the &lt;em&gt;weechat relay&lt;/em&gt; directly.&lt;/p&gt;

&lt;p&gt;Create a SSL relay and configure as below.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;relay.network.max_clients    integer  5
relay.network.password       string   &quot;password&quot;
relay.network.ssl_cert_key   string   &quot;%h/ssl/irc.pem&quot;
relay.port.ssl.irc           integer  12345
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/relay sslcertkey&lt;/code&gt; to load the cert and key without restart.&lt;/p&gt;

&lt;h2 id=&quot;connect-to-relay&quot;&gt;Connect to Relay&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irc.server.ora1.addresses          string   &quot;1.2.3.4/12345&quot;
irc.server.ora1.password           string   &quot;password&quot;
irc.server.ora1.sasl_mechanism     integer  plain
irc.server.ora1.ssl                boolean  on
irc.server_default.ssl_verify      boolean  on
irc.server.ora1.ssl_fingerprint    string   &quot;&amp;lt;sha512&amp;gt;&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We pin the relay&apos;s cert fingerprint for SSL verification.&lt;/p&gt;

&lt;h1 id=&quot;systemd-user-unit&quot;&gt;Systemd user Unit&lt;/h1&gt;

&lt;p&gt;We can create a &lt;a href=&quot;/2021/07/19/systemd/&quot;&gt;systemd user unit&lt;/a&gt; to start launch Weechat in headless mode.&lt;/p&gt;

&lt;p&gt;Create user unit file &lt;em&gt;~/.config/systemd/user/weechat-headless.service&lt;/em&gt; as bellow.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Unit]
Description=A headless WeeChat client and relay service
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/weechat-headless --daemon

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

&lt;p&gt;Enable and start user unit.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; daemon-reload

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;weechat-headless.service
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; start weechat-headless.service

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;systemctl &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; status weechat-headless.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If something wrong, we can send signal SIGHUP to the headless process.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;kill&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-HUP&lt;/span&gt; &amp;lt;pid&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;/h1&gt;

&lt;p&gt;If it reports &quot;unable to load plugin&quot;, please &lt;a href=&quot;https://bbs.archlinux.org/viewtopic.php?id=252579&quot;&gt;install the optional dependencies&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;│22:49:38 =!= | Error: unable to load plugin
│             | &quot;/usr/lib/weechat/plugins/spell.so&quot;: libaspell.so.15:
│             | cannot open shared object file: No such file or
│             | directory
│22:49:38 =!= | If you&apos;re trying to load a script and not a C plugin,
│             | try command to load scripts (/perl, /python, ...)
│22:49:38 =!= | Error: unable to load plugin
│             | &quot;/usr/lib/weechat/plugins/tcl.so&quot;: libtcl.so: cannot
│             | open shared object file: No such file or directory
│22:49:38 =!= | If you&apos;re trying to load a script and not a C plugin,
│             | try command to load scripts (/perl, /python, ...)
│22:49:38 =!= | Error: unable to load plugin
│             | &quot;/usr/lib/weechat/plugins/ruby.so&quot;: libruby.so.2.7:
│             | cannot open shared object file: No such file or
│             | directory
│22:49:38 =!= | If you&apos;re trying to load a script and not a C plugin,
│             | try command to load scripts (/perl, /python, ...)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Github project page blog</title>
   <link href="/2015/10/02/project-page-blog/"/>
   <updated>2015-10-02T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/10/02/project-page-blog</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;blog.example.com&lt;/em&gt; for Github &lt;em&gt;project page&lt;/em&gt;, mainly hosting Chinese posts.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;www.example.com&lt;/em&gt; and &lt;em&gt;example.com&lt;/em&gt; for Github &lt;em&gt;user page&lt;/em&gt;, mainly hosting technical posts.&lt;/p&gt;

    &lt;p&gt;Top domain &lt;em&gt;example.com&lt;/em&gt; can ONLY be used as an alternative to subdomain &lt;em&gt;www&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;project-on-github&quot;&gt;Project on Github&lt;/h1&gt;

&lt;p&gt;Create a repository &lt;em&gt;projectname&lt;/em&gt; on Github.&lt;/p&gt;

&lt;h1 id=&quot;project-page&quot;&gt;Project page&lt;/h1&gt;

&lt;p&gt;Create a branch named exactly as &lt;em&gt;gh-pages&lt;/em&gt; for repository &lt;em&gt;projectname&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;default-branch&quot;&gt;Default branch&lt;/h1&gt;

&lt;p&gt;In Github repository setting, set &lt;em&gt;gh-pages&lt;/em&gt; as the default branch instead of the usual &lt;em&gt;master&lt;/em&gt; one.&lt;/p&gt;

&lt;p&gt;Thus every action like pull and push will take &lt;em&gt;gh-pages&lt;/em&gt; as the default branch.&lt;/p&gt;

&lt;h1 id=&quot;clone&quot;&gt;Clone&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/workspace
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://github.com/username/projectname.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;projectname
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; .git/config
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git branch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h1 id=&quot;template&quot;&gt;Template&lt;/h1&gt;

&lt;p&gt;Choose a &lt;em&gt;Jekyll&lt;/em&gt; template. Here I just use the one for &lt;em&gt;www.example.com&lt;/em&gt;. Copy the necessary files to &lt;em&gt;~/workspace/projectname/&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;customization&quot;&gt;Customization&lt;/h1&gt;

&lt;h2 id=&quot;cname-file&quot;&gt;CNAME &lt;em&gt;file&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;Set the content to be:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;blog.example.com&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Do NOT add the prefix &lt;em&gt;http://&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;freenom-dns&quot;&gt;Freenom DNS&lt;/h2&gt;

&lt;p&gt;We should add a DNS &lt;em&gt;CNAME record&lt;/em&gt; for &lt;em&gt;blog.example.com&lt;/em&gt; on DNS control panel.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;BLOG CNAME username.github.io&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;If without customization, the &lt;em&gt;user page&lt;/em&gt; URL would be &lt;em&gt;username.github.io&lt;/em&gt; while the &lt;em&gt;project page&lt;/em&gt; URL would be &lt;em&gt;username.github.io/projectname&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You can see that in the DNS control panel, we have two &lt;em&gt;CNAME records&lt;/em&gt; to the same destination:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;BLOG CNAME username.github.io&lt;/p&gt;

      &lt;p&gt;WWW CNAME username.github.io&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Whether it is &lt;em&gt;user page&lt;/em&gt; or &lt;em&gt;project page&lt;/em&gt;, the DNS &lt;em&gt;CNAME record&lt;/em&gt; points to the same destination &lt;em&gt;username.github.io&lt;/em&gt;. You should NOT or can NOT set DNS &lt;em&gt;CNAME record&lt;/em&gt; to &lt;em&gt;username.github.io/projectname&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;It Github pages server&apos;s job to determine the real (user or project) page location.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You can also find two DNS &lt;em&gt;A record&lt;/em&gt;:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;␢␢␢␢ A 192.30.252.153&lt;/p&gt;

      &lt;p&gt;␢␢␢␢ A 192.30.252.154&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;The four &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;␢&lt;/code&gt; means leaving the first cell blank. You could replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;␢&lt;/code&gt; with &lt;em&gt;example.com&lt;/em&gt;, but FREENOM will ignore this field. If you replace it with other subdomain like &lt;em&gt;test.example.com&lt;/em&gt;, then the subdomain cannot make use of Github&apos;s CDN service to speed up your site.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The two DNS &lt;em&gt;A records&lt;/em&gt; are making &lt;em&gt;example.com&lt;/em&gt; the alternative URL to &lt;em&gt;www.example.com&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Top domain &lt;em&gt;example.com&lt;/em&gt; can ONLY be the alternative to &lt;em&gt;www&lt;/em&gt; subdomain.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;baseurl-and-url&quot;&gt;&lt;em&gt;baseurl&lt;/em&gt; and &lt;em&gt;url&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;In &lt;em&gt;Jekyll&lt;/em&gt; template, we usually need to use variable like &lt;em&gt;site.url&lt;/em&gt;, &lt;em&gt;site.baseurl&lt;/em&gt;, &lt;em&gt;post.title&lt;/em&gt; etc. For a permanent URL:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;http://username.github.io/projectname/2015/09/23/gentoo/&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;http://blog.example.com&lt;/em&gt; (without trailing slash) is the &lt;em&gt;url&lt;/em&gt; variable, while &lt;em&gt;/projectname&lt;/em&gt; (without trailing slash) is the &lt;em&gt;baseurl&lt;/em&gt; variable.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;For &lt;em&gt;url&lt;/em&gt; in &lt;em&gt;_config.yml&lt;/em&gt;, just set it to &lt;em&gt;http://blog.example.com&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;For &lt;em&gt;baseurl&lt;/em&gt;,
    &lt;ol&gt;
      &lt;li&gt;If use &lt;em&gt;custom url&lt;/em&gt;, then just set it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;;&lt;/li&gt;
      &lt;li&gt;If not, set it to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/projectname&lt;/code&gt; (without trailing trash). When doing test locally on &lt;em&gt;localhost:4000&lt;/em&gt;, you should run &lt;em&gt;jekyll serve –baseurl &apos;&apos;&lt;/em&gt; which sets &lt;em&gt;baseurl&lt;/em&gt; to empty.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Settings in &lt;em&gt;_config.yml&lt;/em&gt; are &lt;em&gt;key&lt;/em&gt;: &lt;em&gt;value&lt;/em&gt; pairs.
    &lt;ol&gt;
      &lt;li&gt;Add least a whitespace after colon (:).&lt;/li&gt;
      &lt;li&gt;The &lt;em&gt;value&lt;/em&gt; can (or not) be enclosed with quotes depending on your preference.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>codepage iocharset</title>
   <link href="/2015/10/02/codepage-iocharset/"/>
   <updated>2015-10-02T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/10/02/codepage-iocharset</id>
   <content type="html">&lt;h1 id=&quot;1-introduction&quot;&gt;1 Introduction&lt;/h1&gt;

&lt;p&gt;In Linux, X or console is usually garbled with squares and unknown characters, &lt;strong&gt;mojibak&lt;/strong&gt; - the garbled text that is the result of text being decoded using an unintended character encoding. The screen is in a mess with garbage messages of either filename or file contents, especially of Windows MSDOS/FAT/NTFS filesystem. In this post, I will discuss the reason of garbled screen. And I also try to elaborate the process of storage, transfer, and display characters in computer.&lt;/p&gt;

&lt;p&gt;There are mainly four parts to be clarified, namely &lt;em&gt;Character&lt;/em&gt;, &lt;em&gt;File&lt;/em&gt;, &lt;em&gt;Font&lt;/em&gt; and &lt;em&gt;Locale&lt;/em&gt;. Character refers to the basics of language of personal interest, including &lt;em&gt;Character set&lt;/em&gt; and &lt;em&gt;Character encoding&lt;/em&gt;. &lt;em&gt;File&lt;/em&gt; involves &lt;em&gt;filesystem&lt;/em&gt; and &lt;em&gt;File Content&lt;/em&gt;, while &lt;em&gt;Font&lt;/em&gt; requires the support of &lt;em&gt;fontconfig&lt;/em&gt; and &lt;em&gt;locale&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Dispalying Chinese filename and file contents of MSDOS/FAT/NTFS filesystem within Linux is troublesome in that it involves &lt;em&gt;locale&lt;/em&gt;, &lt;em&gt;kernel&lt;/em&gt;, &lt;em&gt;userspace program&lt;/em&gt;, &lt;em&gt;filesystem&lt;/em&gt;, &lt;em&gt;X&lt;/em&gt;, &lt;em&gt;Character&lt;/em&gt; etc.&lt;/p&gt;

&lt;h1 id=&quot;2-character&quot;&gt;2 Character&lt;/h1&gt;

&lt;p&gt;Computers themselves do not understand printed text as a human would. For computers, every character of text is represented by a number (more concretely &lt;em&gt;binary digit&lt;/em&gt;). Traditionally, each set of numbers used to represent alphabets and characters (known as a &lt;em&gt;coding system&lt;/em&gt;, &lt;em&gt;encoding&lt;/em&gt;, or &lt;em&gt;character set&lt;/em&gt;) was limited in size due to limitations in computer hardware.&lt;/p&gt;

&lt;p&gt;Windows/Linux kernel or userspace application (read/write MSDOS/FAT/NTFS file content) must understand both the &lt;em&gt;character set&lt;/em&gt; and &lt;em&gt;character encoding&lt;/em&gt;. We usually take &lt;em&gt;character encoding&lt;/em&gt; and &lt;em&gt;character set&lt;/em&gt; for each other without explicitly clarification, for they always assume each other. For example, Unicode usualy implies UCS-2 or UTF-16. Keep in mind: &lt;em&gt;character set&lt;/em&gt; is meaningless withtout &lt;em&gt;character encoding&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Computer only knows 0 and 1. It does not understand &lt;em&gt;graphical character&lt;/em&gt; as human being.&lt;/li&gt;
  &lt;li&gt;Kernel is a special superior application to those of userspace.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;21-character-set&quot;&gt;2.1 Character Set&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;字符/语言的存储表达。目前的电子计算设备只能存储和运算数字，很显然，对于非数字信息，必须有一个“转义”过程，而这个“转义”规则本身并不能完全被存储，一部分需要人工设置。我们讨论的主要对象是“字符集”，如中文字符集，英文字符集，日文字符集等。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;字符集 “character set”。当我需要使用（存储、传输、显示等）字符时（如你要浏览俄文网页），首先规定一个字符范围（一般是本国语言涉及到的字符），范围内的字符的使用规则都有确切的定义，这个范围就是字符集。字符集中的每个字符将使用一个唯一的数字指代，叫“code point”。字符集其实是一张字符和数字间的逻辑映射表。&lt;/p&gt;

    &lt;p&gt;这里我要对“逻辑”二字解释一下。计算机设计中，我们通常需要用到逻辑的概念，譬如逻辑内存，逻辑地址空间，表示虚拟的、脱离实际计算机设备的概念。字符集就是逻辑概念，只对计算机设计者有意义，对计算机本身来说z这张表格没有任何意义。这张字符集表格可以写在纸张上，譬如第0项是“你”，第1024项是“好”，计算机是理解不了这个表的。&lt;/p&gt;

    &lt;p&gt;Microsoft designs its own &lt;em&gt;character set&lt;/em&gt; standard to render different lanauge characters, which is called &lt;em&gt;codepage&lt;/em&gt;. The &lt;em&gt;cp437&lt;/em&gt; is for United States and Canada English characters, while the &lt;em&gt;cp936&lt;/em&gt; is for Chinese characters.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;字符集的定义在早期是各自为战的状态，国家、组织等某个地区的权威为各自区域/国家范围内使用到的字符定义字符集。当你的计算机系统只用到本区域/国家的字符时，并没有什么问题。&lt;/p&gt;

    &lt;p&gt;但当你需要使用其它区域/国家字符集的字符时，就会出问题，因为不同的字符集可能有“code point”冲突。日本人的日文字符集里，可能数字100是日文中的“他”；泰国的给泰文字符集里数字100则指泰文中“好”。很显然使用日文字符集的计算机上无法存储、传输、显示泰文的“好”字。&lt;/p&gt;

    &lt;p&gt;为了能让计算机同时使用各区域/国家的语言/字符，有必要设计一个包含尽可能多字符的字符集，对全世界的所有语言字符设置一个统一字符集，这个字符集表肯定非常大，就是我们耳熟能详的“Unicode”字符集。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;同一语言，可以有不同的字符集。譬如中文可以有 Windows “cp936”字符集，可以有 Unicode 字符集，我们自己可以设计一个，只要实力足够说服软件和操作系统使用你设置的字符集。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;22-character-encoding&quot;&gt;2.2 Character Encoding&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;With just a table of &lt;em&gt;character set&lt;/em&gt;, computer can NOT handle (understand, store, transfer, display etc.) characters. Before that, &lt;em&gt;code point&lt;/em&gt; should be encoded into computer&apos;s language - &lt;em&gt;binary digit&lt;/em&gt;, which is the responsibility of &lt;em&gt;character encoding&lt;/em&gt;. The simplest way to encode is just use the index/code point of characters in &lt;em&gt;chatacter set&lt;/em&gt; table. But that is not enough.&lt;/p&gt;

    &lt;p&gt;There are over 20,000 Chinese characters and most of their code points take at least two bytes no matter in &lt;em&gt;Unicode&lt;/em&gt; or &lt;em&gt;cp936&lt;/em&gt;. How does computer orgnazie the two bytes, i.e. Unicode 6E49? With &lt;em&gt;big endian&lt;/em&gt; (6E first) or &lt;em&gt;little endian&lt;/em&gt; (49 first)? Aside, the transfer order of the two bytes online counts when the network MTU is limited.&lt;/p&gt;

    &lt;p&gt;Does computer use &lt;em&gt;fixed&lt;/em&gt; or &lt;em&gt;varied&lt;/em&gt; width/bits to organize &lt;em&gt;code point&lt;/em&gt;? If fixed width (say 16 bits), then code point 128 and 1024 are recoginized by computer as 0x0080 and 0x0400 respectively. If varied width, code point 128 and 1024 might be 0x80 and 0x400.&lt;/p&gt;

    &lt;p&gt;In varied width encoding, when encountering two bytes, how should computer treat them? Treat them as a single code point or two sequencial code points? Need pattern support.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;That is where &lt;em&gt;chracter encoding&lt;/em&gt; comes into effect. &lt;em&gt;encoding&lt;/em&gt; takes care of representing &lt;em&gt;human-being code point&lt;/em&gt; as &lt;em&gt;computer binary digit&lt;/em&gt;. For a programmer, ASCII (7-bit encoding) might be the most famous &lt;em&gt;character encoding&lt;/em&gt; method, others are ISO 8859 series, UTF-8, GBK etc. By the way, character set Unicode itself is also a &lt;em&gt;character encoding&lt;/em&gt; (usually implies UCS-2 Or UTF-16).&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;code point&lt;/em&gt; is designed by human beings and a &lt;em&gt;logical&lt;/em&gt; table which cannot be recognized/understood by computer. It should be &lt;em&gt;encoded&lt;/em&gt; into &lt;em&gt;binary digit&lt;/em&gt;, which is a process of converting human language to computer language.&lt;/p&gt;

    &lt;p&gt;Chinese &quot;严&quot;&apos;s Unicode code point is 4E25, but its UTF-8 encoding is E4B8A5. So &lt;em&gt;character encoding&lt;/em&gt; does NOT guarantee the encoded binary digit equals to original &lt;em&gt;code point&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A &lt;em&gt;character set&lt;/em&gt; might correspond to different &lt;em&gt;character encodings&lt;/em&gt;. For example, Unicode can be encoded into UCS-2, UTF-16, UTF-8, UCS-4 etc. However, reversely a &lt;em&gt;character encoding&lt;/em&gt; determines its &lt;em&gt;character set&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;For example, if a file is stored on disk as ASCII, the &lt;em&gt;character set&lt;/em&gt; must be &lt;em&gt;cp437&lt;/em&gt; on Windows. GB2312 assumes &lt;em&gt;cp20936&lt;/em&gt;, GBK assumes &lt;em&gt;cp936&lt;/em&gt; while GB18030 assumes &lt;em&gt;cp54936&lt;/em&gt;. GB18030 is a varied width encoding method with some characters encoded into 4 bytes. However Windows &lt;em&gt;code page&lt;/em&gt; only support single-byte or doulbe-byte encoding, &lt;em&gt;cp54936&lt;/em&gt; does NOT actually implemented on Windows. It is just a name reservation.
4.Though a language&apos;s characters can be represented by different &lt;em&gt;character sets&lt;/em&gt; and &lt;em&gt;character encodings&lt;/em&gt;, most often, those different sets and/or encodings are &lt;em&gt;downward compatible&lt;/em&gt; (ASCII -&amp;gt; GB2312 -&amp;gt; GBK -&amp;gt; GB18030). By the way, GBK is not 国家标准.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;通常看到网页上提到“内码”，这个内码就是内核处理字符的“character set”。早期 Windows 使用的是“codepage”，自从 Windows 2000 后，Windows 内核默认使用 Unicode，但依然支持那些依然依赖 codepage 编码的应用。Nowadays, both Linux and Windows kernel uses Unicode character set. So applications that takes Unicode character set can run smoothly. If application uses other character set like GBK, then we should set &lt;em&gt;default character set&lt;/em&gt; for &lt;em&gt;non-Unicode Programs&lt;/em&gt; in Windows control panel.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;23-character-setencoding-evolution&quot;&gt;2.3 Character set/encoding evolution&lt;/h2&gt;

&lt;p&gt;The most common (or at least the most widely accepted) character set is &lt;strong&gt;ASCII&lt;/strong&gt; (American Standard Code for Information Interchange) for modern English. ASCII is strictly seven-bit, meaning that it uses bit patterns representable with seven binary digits, which provides a range of 0 to 127 in decimal.&lt;/p&gt;

&lt;p&gt;Although ASCII was enough for communication in modern English, in other European languages that include accented characters, things were not so easy. The ISO 8859 standards were developed to meet these needs. They were backwards compatible with ASCII, but instead of leaving the eighth bit blank, they used it to allow another 127 characters in each encoding.&lt;/p&gt;

&lt;p&gt;ISO 8859&apos;s limitations soon came to light, and there are currently 15 variants of the ISO 8859 standard (8859-1 through to 8859-15). Outside of the ASCII-compatible byte range of these character sets, there is often conflict between the letters represented by each byte.&lt;/p&gt;

&lt;p&gt;To complicate interoperability between character encodings further, Windows-1252 is used in some versions of Microsoft Windows instead for Western European languages. This is a super-set of ISO 8859-1, however it is different in several ways. These variants do all retain ASCII &lt;em&gt;compatibility&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&quot;231-unicode-utf-8&quot;&gt;2.3.1 Unicode UTF-8&lt;/h3&gt;

&lt;p&gt;Unicode throws away the traditional single-byte limit of character sets. It uses 17 &quot;planes&quot; of 65,536 code points to describe a maximum of 1,114,112 characters. As the first plane, aka. &quot;Basic Multilingual Plane&quot; or BMP, contains almost every character a user will ever need. Many have made the &lt;em&gt;wrong&lt;/em&gt; assumption that Unicode was a 16-bit character set (earlier Unicode encoding do indeed use 16-bit unit like UCS-2 and UTF-16).&lt;/p&gt;

&lt;p&gt;Unicode has been mapped/encoded in many different ways, but the two most common are UTF (Unicode Transformation Format) and UCS (Universal Character Set). A number after UTF indicates the number of bits in one unit, while the number after UCS indicates the number of bytes, like UCS-2. UTF-8 has become the most widespread means for the interchange of Unicode text as a result of its eight-bit clean nature; it is therefore the subject of this document.&lt;/p&gt;

&lt;p&gt;When Unicode first started gaining momentum in the software world, multibyte character sets were not well suited to languages like C, which is the base language of most commonly used programs. Even today, some programs are not able to handle UTF-8 properly. Fortunately the majority of programs, especially the common ones, are supported.&lt;/p&gt;

&lt;p&gt;为每一个字符分配全球唯一的一个数字，但是并没有规定这个数字的表示方法。数字的表示方法由 UTF 规范规定。UTF-16 使用 2 个字节表示一个 UNICODE 数字，但是对于 &amp;gt;=216的数字使用 4 字节来表达。UTF-8 则对于 &amp;lt;127 的数字采取单字节表示，大于 127 的数字要根据其大小选择 2~6 个字节进行表示。UNICODE 在程序内部则简单的使用 unsigned long 即可表示一个字符。&lt;/p&gt;

&lt;h2 id=&quot;24-more-on-character&quot;&gt;2.4 More on Character&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;When storing, transferring, and displaying, computers refer to &lt;em&gt;character encoding&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;When doing conversion, compuers refer to &lt;em&gt;code point&lt;/em&gt; as the middle relay: i.e. GBK -&amp;gt; UTF-8:
    &lt;ol&gt;
      &lt;li&gt;Use GBK encoding method to get the &lt;em&gt;cp936&lt;/em&gt; code point;&lt;/li&gt;
      &lt;li&gt;Convert &lt;em&gt;cp936&lt;/em&gt; code point to Unicode code point by system API call;&lt;/li&gt;
      &lt;li&gt;Encode Unicode code point to UTF-8.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;When programming, an &lt;em&gt;unsigned long&lt;/em&gt; will hold a Unicode code point.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;3-file&quot;&gt;3 File&lt;/h1&gt;

&lt;h2 id=&quot;31-filesystem&quot;&gt;3.1 filesystem&lt;/h2&gt;

&lt;p&gt;A filesystem is the methods and data structures that an operating system uses to keep track of files on a disk or partition; that is, the way the files are organized on the disk. The word is also used to refer to a partition or disk that is used to store the files or the type of the filesystem. It only cares about the meta data of indexing, locating, organizing files.&lt;/p&gt;

&lt;h2 id=&quot;32-windows-ntfs&quot;&gt;3.2 Windows NTFS&lt;/h2&gt;

&lt;p&gt;NTFS is superior to FAT. Most of the disucssion on FAT below applies to NTFS as well. One difference is that NTFS does not need &lt;em&gt;codepage&lt;/em&gt; anymore. The reason of omitting codepage is not clear yet. Maybe NTFS uses Unicode for short filename.&lt;/p&gt;

&lt;h2 id=&quot;33-windows-fat&quot;&gt;3.3 Windows FAT&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.win.tue.nl/~aeb/linux/fs/fat/fat.html#toc1&quot;&gt;The FAT filesystem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The traditional DOS filesystem types are MSDOS, FAT12 and FAT16. Here FAT stands for &lt;em&gt;File Allocation Table&lt;/em&gt;: the disk is divided into &lt;em&gt;clusters&lt;/em&gt;, the &lt;em&gt;unit&lt;/em&gt; used by the file allocation, and each FAT entry describes which clusters are used by which files. The number of sectors per cluster is given in the &lt;em&gt;boot sector&lt;/em&gt; byte 13.&lt;/p&gt;

&lt;p&gt;Since MSDOS is nearly dead. I will not go into details.&lt;/p&gt;

&lt;h3 id=&quot;331-fat-disk-layout&quot;&gt;3.3.1 FAT disk Layout&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;First the boot sector (at relative address 0), and possibly other stuff. Together these are the Reserved Sectors. Usually the boot sector is the only reserved sector.&lt;/li&gt;
  &lt;li&gt;Then the FAT entries (following the reserved sectors; the number of reserved sectors is given in the boot sector, bytes 14-15; the length of a sector is found in the boot sector, bytes 11-12). The File Allocation Table has one entry per cluster. This entry uses 12, 16 or 28 bits for FAT12, FAT16 and FAT32.&lt;/li&gt;
  &lt;li&gt;Then the Root Directory (following the FATs; the number of FATs is given in the boot sector, byte 16; each FAT entry has a number of sectors given in the boot sector, bytes 22-23).&lt;/li&gt;
  &lt;li&gt;Finally the Data Area (following the root directory; the number of root directory entries is given in the boot sector, bytes 17-18, and each directory entry takes 32 bytes; space is rounded up to entire sectors).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;332-12-16-vfat-32&quot;&gt;3.3.2 12 16 VFAT 32&lt;/h3&gt;

&lt;p&gt;DOS 1.0 and 2.0 used FAT12. The maximum possible size of a FAT12 filesystem (volume) was 8 MB (4086 clusters of at most 4 sectors each).&lt;/p&gt;

&lt;p&gt;DOS 3.0 introduced FAT16. Everything very much like FAT12, only the FAT entries are now 16 bit. Now the maximum volume size was 32 MB, mostly since DOS 3.0 used 16-bit sector numbers. This was fixed in DOS 4.0 that uses 32-bit sector numbers. Now the maximum possible size of a FAT16 volume is 2 GB (65526 clusters of at most 64 sectors each).&lt;/p&gt;

&lt;p&gt;In Windows 95 a variation was introduced: VFAT. VFAT (Virtual FAT) is FAT together with long filenames (LFN), that can be up to 255 bytes long. The implementation is an ugly hack. These long filenames are stored in special directory entries. VFAT is not commonly used due to its subsequent FAT32.&lt;/p&gt;

&lt;p&gt;FAT32 was introduced in Windows 95 OSR 2 and quickly replaced VFAT on Windows system. It is not supported by Windows NT. Everything very much like FAT16, only the FAT entries are now 32 bits of which the top 4 bits are reserved. The bottom 28 bits have meanings similar to those for FAT12, FAT16. For FAT32: Cluster size used: 4096-32768 bytes. The maximum file size on a FAT32 filesystem is one byte less than 4 GiB (4294967295 bytes).&lt;/p&gt;

&lt;p&gt;To be compatible with FAT12 FAT16, when you create a long filename (longer than 8.3) with VFAT, FAT32, or NTFS, the filesystem actually creates two different filenames. One is the actual long filename. This name is visible to Windows 95, Windows 98, and Windows NT (4.0 and later). The second filename is called an MS-DOS® alias. An MS-DOS alias is an abbreviated form of the long filename. The filesystem creates the MS-DOS alias by taking the first six characters of the long filename (not counting spaces), followed by the tilde [~] and a numeric trailer. For example, the filename Brien&apos;s Document.txt would have an alias of BRIEN&apos;~1.txt.&lt;/p&gt;

&lt;p&gt;Microsoft operating systems use the following rule to distinguish between FAT12, FAT16 and FAT32. First, compute the number of clusters in the data area (by taking the total number of sectors, subtracting the space for reserved sectors, FATs and root directory, and dividing, rounding down, by the number of sectors in a cluster). If the result is less that 4085 we have FAT12. Otherwise, if it is less than 65525 we have FAT16. Otherwise FAT32.&lt;/p&gt;

&lt;h3 id=&quot;333-shortlong-filename&quot;&gt;3.3.3 Short/Long filename&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;filename&lt;/em&gt; is one kind of &lt;em&gt;filesystem&lt;/em&gt; meta data which usually causes garbled screen. FAT12 and FAT16 only support/implement short filename, while VFAT, FAT32 and NTFS implement both short and long filename. Short filename is case &lt;em&gt;insensitive&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;No matter what MSDOS/FAT/NTFS version is used, short filename (on VFAT and FAT32 filesystem) is stored with Windows codepage (i.e. cp936) while long filename (on FAT12 and FAT16 filesystem) is stored with Unicode (i.e. UCS-2 and UTF-16) . NTFS stores filename in Unicode despite of short or long filename.&lt;/p&gt;

&lt;p&gt;We can even disable the shortname creation on NTFS which will improve system performance. However some old applications still depend on shortname and would not locate the correct filename.&lt;/p&gt;

&lt;p&gt;Garbled &lt;em&gt;filename&lt;/em&gt; with squares and weird characters is when your computer incorrectly display filesystem filename on console or X.&lt;/p&gt;

&lt;h2 id=&quot;34-linux-msdosfatntfs-support&quot;&gt;3.4 Linux MSDOS/FAT/NTFS support&lt;/h2&gt;

&lt;p&gt;When we say &lt;em&gt;Linux supports Windows MSDOS/FAT/NTFS filesystem&lt;/em&gt;, it means MSDOS/FAT/NTFS part is enabled (Y or M) in Linux kernel. Pay attention to &lt;em&gt;kernel&lt;/em&gt; keyword. If a filesystem is supported by operating system, it is indeed supported by the kernel of that operating system, including mounting the filesystem, updating filesystem meta data (creating/deleting/updating files etc.), and displaying filename on console and X which is the focus in the following discussion.&lt;/p&gt;

&lt;p&gt;For short/long filename to be displayed properly under Linux, we need:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Enable corresponding MSDOS/FAT/NTFS in kernel.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; File systems  ---&amp;gt;
     &amp;lt;*&amp;gt; FUSE (Filesystem in Userspace) support
     ...
     DOS/FAT/NT Filesystems  ---&amp;gt;
     &amp;lt;*&amp;gt; MSDOS fs support
     &amp;lt;*&amp;gt; VFAT (Windows-95) fs support
     (437) Default codepage for FAT
     (iso8859-1) Default iocharset for FAT
     &amp;lt;M&amp;gt; NTFS file system support
     [ ]   NTFS debugging support
     [ ]   NTFS write support 
     ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;There is an option &lt;em&gt;MSDOS fs support&lt;/em&gt; which is almost dead and can only be found on floppy disk. I will focus only FAT/NTFS in the following sections.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable &lt;em&gt;codepage&lt;/em&gt; and &lt;em&gt;iocharset&lt;/em&gt; in kernel.&lt;/p&gt;

    &lt;p&gt;Apart from the basic support in step 1, we should enable NLS options (mainly for displaying short/long filename) in Linux kernel configuration menu, namely - &lt;em&gt;Native Language Support&lt;/em&gt;. NLS will build those &lt;em&gt;character encoding&lt;/em&gt; into kernel (Y or M) for decoding/converting filename to kernel Unicode and then encoding Unicode to &lt;em&gt;locale&lt;/em&gt;. It is important to not become confused. For the most part, the only thing that needs to be done is to build &lt;em&gt;UTF-8 NLS&lt;/em&gt; support into the kernel, and change the &lt;em&gt;Default NLS option&lt;/em&gt; to &lt;em&gt;utf8&lt;/em&gt; if we don&apos;t mount Windows MSDOS/FAT or Apple HFS and would like to maintain a clean UTF-8 system.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; File Systems --&amp;gt;
   Native Language Support --&amp;gt;
     (utf8) Default NLS Option
     ...
     &amp;lt;M&amp;gt;   Simplified Chinese charset (CP936, GB2312)
     ...
     ## (Also &amp;lt;*&amp;gt; or &amp;lt;M&amp;gt; other character sets that are in use in the system&apos;s FAT filesystems or Joilet CD-ROMs.)
     &amp;lt;*&amp;gt; UTF-8 NLS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Take MSDOS/FAT/NTFS for example, filename is encoded by codepage (short filename) or Unicode (long filename) and stored on disk. Enabled NLS options (i.e. cp936) decode binary digits (i.e. GBK or GB2312) to kernel Unicode (through kernel API) and then to system &lt;em&gt;locale&lt;/em&gt; before displaying. The first option (set to &lt;em&gt;utf8&lt;/em&gt;) is the default NLS used for decoding when mounting filesystem. You can also find that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NLS_CODEPAGE_CP936&lt;/code&gt; (decode Chinese short filename) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NLS_UTF8&lt;/code&gt; (encode filename Unicode to system UTF-8 &lt;em&gt;locale&lt;/em&gt;) are enabled.&lt;/p&gt;

    &lt;p&gt;You can notice many NLS options started with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ISO 8859-&lt;/code&gt; of them most are not necessary for Chinese users. Russian users need to enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NLS_KOI8_R&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NLS_CODEPAGE_CP936&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;NLS is designed for not only MS-DOS/Windows filesystem, but other operating system filesystem&lt;/strong&gt; like Apple HFS file system that uses MAC codepages. You can also enable those NLS support if needed.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;cjktty patch for Chinese on console.&lt;/p&gt;

    &lt;p&gt;In order to display Chinese on console, we need &lt;a href=&quot;http://www.fangxiang.tk/2015/09/18/git-diff-patch/&quot;&gt;cjktty patch&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;mount&lt;/em&gt; arguments.&lt;/p&gt;

    &lt;p&gt;Having enabled MSDOS/FAT/NTFS filesystem and corresponding NLS in kernel, we then specify add those NLS to mount command through &lt;em&gt;codepage&lt;/em&gt;, &lt;em&gt;iocharset&lt;/em&gt; and/or &lt;em&gt;utf8&lt;/em&gt; arguments. Suppose a FAT32/NTFS partition with Chinese filename and file contents, they can be mounted in Linux of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zh_CN.GBK&lt;/code&gt; &lt;em&gt;locale&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c&quot;&gt;# mount -t vfat -o codepage=936,iocharset=cp936 /dev/sda5 /mnt/data&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# mount -t ntfs-3g -o utf8 /dev/sdb7 /mnt/misc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Most of the time, we use &lt;em&gt;-t msdos&lt;/em&gt; to mount FAT12 and FAT16; use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t vfat&lt;/code&gt; to mound VFAT and FAT32. If you don&apos;t use special mount options (i.e. English language users), &lt;em&gt;-t&lt;/em&gt; mouint option can be omitted since mount detects filesystem itself.&lt;/p&gt;

    &lt;p&gt;There are three options need special attention: &lt;em&gt;codepage&lt;/em&gt;, &lt;em&gt;iocharset&lt;/em&gt;, and &lt;em&gt;utf8&lt;/em&gt;. Possible NLS options must be enabled in kernel. We can set their default values in kernel - &lt;em&gt;Default codepage for FAT&lt;/em&gt;, &lt;em&gt;Default iocharset for FAT&lt;/em&gt;, &lt;em&gt;Default NLS Option&lt;/em&gt; which can be overriden in mount command. &lt;em&gt;codepage&lt;/em&gt;/&lt;em&gt;iocharset&lt;/em&gt;/&lt;em&gt;utf8&lt;/em&gt; arguments support Windows MSDOS/FAT/NTFS short/long filename decoding/conversion.&lt;/p&gt;

    &lt;p&gt;In short, the &lt;em&gt;codepage&lt;/em&gt; option is for &lt;em&gt;short&lt;/em&gt; filename, and the &lt;em&gt;iocharset&lt;/em&gt; option is for &lt;em&gt;long&lt;/em&gt; filename. The &lt;em&gt;utf8&lt;/em&gt; option alone is to replace &lt;em&gt;iocharset=utf8&lt;/em&gt;/&lt;em&gt;nls=utf8&lt;/em&gt; which is not recommended.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;341-codepage&quot;&gt;3.4.1 codepage&lt;/h3&gt;

&lt;p&gt;In old Windows system, both filesystem meta data and file contents are stored as codepage. But in this section, I only talk short filename display under Linux.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;codepage&lt;/em&gt; option is needed for &lt;em&gt;vfat&lt;/em&gt;-compatible (MSDOS/FAT) and &lt;em&gt;smbfs&lt;/em&gt; filesystems. It should be set to the codepage number used under MS-DOS/Windows in your country.&lt;/p&gt;

&lt;p&gt;NLS &lt;em&gt;codepage&lt;/em&gt; option sets the codepage number for converting to shortname characters on Windows MSDOS/FAT. By default, &lt;em&gt;mount&lt;/em&gt; will take &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAT_DEFAULT_CODEPAGE&lt;/code&gt; in Linux kernel. Short filename is encoded by codepage and should be decoded and then converted to kernel Unicode before displaying.&lt;/p&gt;

&lt;p&gt;When should we use &lt;em&gt;codepage&lt;/em&gt;? MSDOS/FAT12/FAT16 only support short filename of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8.3&lt;/code&gt; format by codepage (i.e. Chinese cp936) encoding (i.e. GB2312 or GBK). If you mount such partitions, NLS &lt;em&gt;cp936&lt;/em&gt; must be enabled in Linux kernel (M or Y) and &lt;em&gt;codepage=936&lt;/em&gt; argument be added to mount command such that the short filename can be displayed.&lt;/p&gt;

&lt;p&gt;Say you have a FAT32 parition and mount it with option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t msdos -o codepage=936&lt;/code&gt;, filenames are displayed short. If you want to display true long filename, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t vfat&lt;/code&gt; or just remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; option instead.&lt;/p&gt;

&lt;p&gt;Most of the time, we needn&apos;t &lt;em&gt;codepage&lt;/em&gt; mount argument at all since MSDOS/FAT12/FAT15 and applications depending on short filename are almost dead. Currently, VFAT and FAT32 support long filename by Unicode encoding. Actually, we do omit this argument as short filename is almost deprecated.&lt;/p&gt;

&lt;p&gt;When we use &lt;em&gt;codepage=936&lt;/em&gt;, the kernel:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Find the relevant NLS &lt;em&gt;cp936&lt;/em&gt; module;&lt;/li&gt;
  &lt;li&gt;Decode short filename to GBK/GB2312 code point;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Convert the code point to Unicode code point;&lt;/p&gt;

    &lt;p&gt;Kernel operates characters with Unicode.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;342-iocharset&quot;&gt;3.4.2 iocharset&lt;/h3&gt;

&lt;p&gt;Character set used for converting between the encoding used for user visible long filename characters (display on screen) and 16 bit Unicode characters (long filename are encoded by Unicode UTF-16). Long filenames are stored on disk in Unicode format (usually UTF-16), but Unix for the most part doesn&apos;t know how to deal with Unicode. By default, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAT_DEFAULT_IOCHARSET&lt;/code&gt; setting is used. Since only VFAT/FAT32/NTFS support long filename, when mounting MSDOS/FAT12/FAT16, you should not use &lt;em&gt;iocharset&lt;/em&gt; argument.&lt;/p&gt;

&lt;p&gt;Filesystems with MS-DOS or Windows origin (i.e.: vfat, ntfs, smbfs, cifs, iso9660, udf) need the &lt;em&gt;iocharset&lt;/em&gt; mount option in order for non-ASCII characters in file names to be interpreted properly. The value of this option should be the same as the character set of your &lt;em&gt;locale&lt;/em&gt;, adjusted in such a way that the kernel understands it. This works if the relevant character set definition (found under File systems -&amp;gt; Native Language Support) has been compiled into the kernel or built as a module.&lt;/p&gt;

&lt;p&gt;This argument should NOT be ignored since it controls the display of true long filename unless your kernel Default NLS Option (&lt;em&gt;utf8&lt;/em&gt; in above kernel configuration menu) equals to your system &lt;em&gt;locale&lt;/em&gt;. It should be set to be the corresponding &lt;em&gt;character encoding&lt;/em&gt; of your Linux system &lt;em&gt;locale&lt;/em&gt;. If locale is not UTF-8, like GBK or GB2312, set it to &lt;em&gt;iocharset=cp936&lt;/em&gt;. If locale is UTF-8, use &lt;em&gt;utf8&lt;/em&gt;,  &lt;em&gt;iocharset=utf8&lt;/em&gt;/&lt;em&gt;nls=utf8&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The argument of doing UTF-8 translations with just &lt;em&gt;utf8&lt;/em&gt; (NOTE: &quot;iocharset=utf8&quot; or &lt;em&gt;nls=utf8&lt;/em&gt; is not recommended) is recommended if unsure. If &lt;em&gt;iocharset=utf8&lt;/em&gt; mount argument is used, Linux kernel VFAT module will be case sensitive which is incompatible with Windows short filename which does not differentiate filename character case. &lt;em&gt;utf8&lt;/em&gt; alone does not have this side effect. Attention: the counterpart of NTFS &lt;em&gt;iocharset&lt;/em&gt; option is now deprecated and renamed as &lt;em&gt;nls&lt;/em&gt;. Details refer to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man mount&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When we use &lt;em&gt;iocharset=cp936&lt;/em&gt;, the kernel:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Read the UTF-16 long filename directly from FAT32/NTFS;&lt;/li&gt;
  &lt;li&gt;Get the long filename Unicode code point;&lt;/li&gt;
  &lt;li&gt;Find the relevant NLS &lt;em&gt;cp936&lt;/em&gt; module;&lt;/li&gt;
  &lt;li&gt;Encode the Unicode code point to GBK/GB2312&lt;/li&gt;
  &lt;li&gt;Return the GBK code userspace program like X, file editor etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;We notice that &lt;em&gt;codepage&lt;/em&gt; option is decided basically by the language of Windows users while &lt;em&gt;iocharset&lt;/em&gt; is set based on Linux &lt;em&gt;locale&lt;/em&gt;. The NLS value set for &lt;em&gt;iocharset&lt;/em&gt; and &lt;em&gt;codepage&lt;/em&gt; should be enabled in kernel - Native Language Support.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;343-logics&quot;&gt;3.4.3 Logics&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;There is a Windows FAT32 partition with Chinese filenames. Each file has two filenames - the short one and the long one.&lt;/li&gt;
  &lt;li&gt;Short filename is encoded by codepage &lt;em&gt;cp936&lt;/em&gt; / GBK.&lt;/li&gt;
  &lt;li&gt;Long filename is encoded by Unicode / UTF-16.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mount -t vfat -o codepage=936,nls=cp936 /dev/sda1 /mnt/data&lt;/code&gt; on Linux with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zh_CH.GBK&lt;/code&gt; locale.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Kernel &lt;em&gt;cp936&lt;/em&gt; module decodes and convert short filename to Unicode&lt;/p&gt;

    &lt;p&gt;If use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t msdos&lt;/code&gt; option, the default true filename will be the short one.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Linux kernel decodes UTF-16 binary digits to Unicode directly (Linux kernel uses Unicode naturally).&lt;/p&gt;

    &lt;p&gt;Then Unicode code points are encoded into GBK.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;GBK codes are transferred from kernel to userspace ls, thunar, emacs etc.&lt;/li&gt;
  &lt;li&gt;Userspace application decode GBK codes and transfer back to kernel input/output system for display.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;35-file-content&quot;&gt;3.5 File Content&lt;/h2&gt;

&lt;p&gt;After talking about &lt;em&gt;filesystem&lt;/em&gt; and &lt;em&gt;filename&lt;/em&gt;, let&apos;s turn to &lt;em&gt;file content&lt;/em&gt;. &lt;em&gt;filesystem&lt;/em&gt; does NOT either care about or know &lt;em&gt;file content&lt;/em&gt;. The former only takes care of file meta data to organize directory, file location, indexing, etc. by system kernel, while the later are real data of user/userspace application interest.&lt;/p&gt;

&lt;p&gt;Operating system kernel is responsible of filesystem support. For file contents, they are owned by user or userspace program (like file editor). Therefore, displaying filename (need kernel support) is different from displaying file content (need userspace program support) on screen (most of the time, it is X in Linux).&lt;/p&gt;

&lt;p&gt;For example, we have a GBK-encoded TXT file contents on FAT32 partition and want to display the file, the corresponding program for displaying should support GBK character encoding.&lt;/p&gt;

&lt;p&gt;If we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;less&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat&lt;/code&gt; command to display the GBK TXT file, the X screen will be garbled, for those commands do not know GBK at all. However, if we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emacs&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gedit&lt;/code&gt; to open the file, GBK TXT will be well rendered on X screen.&lt;/p&gt;

&lt;h1 id=&quot;4-font&quot;&gt;4 Font&lt;/h1&gt;

&lt;h2 id=&quot;41-fonts&quot;&gt;4.1 Fonts&lt;/h2&gt;

&lt;p&gt;Fonts is the graphical skeleton of characters to display. The common western fonts are classified into &lt;em&gt;sans&lt;/em&gt; (like &lt;em&gt;Courier&lt;/em&gt;), &lt;em&gt;serif&lt;/em&gt; (like Times New Man) and &lt;em&gt;monospace&lt;/em&gt;. Mostly used Chinese fonts are &quot;宋体&quot;, &quot;楷体&quot;, &quot;黑体&quot; etc.&lt;/p&gt;

&lt;p&gt;When filename or file content is displayed, a good font design help relieve eye and add aesthetic sense.&lt;/p&gt;

&lt;h2 id=&quot;42-fontconfig&quot;&gt;4.2 Fontconfig&lt;/h2&gt;

&lt;p&gt;Usually on our system, we have a set of different fonts, like &quot;宋体&quot; for Chinese, &quot;Times&quot; for English, etc. What is more, different fonts may overlap. For example, &quot;宋体&quot; can also be used to display English letters; Google &quot;Nato&quot; can display Chinese, Japanese and Korean. So when system display a character which is covered by several fonts, which font should be chosen? This is when &lt;em&gt;fontconfig&lt;/em&gt; come into effect. Fontconfig not only chooses the font to display, but also renders the chosen font in a more aesthetic way.&lt;/p&gt;

&lt;p&gt;Fontconfig (or &lt;em&gt;fontconfig&lt;/em&gt;) is a free software program library designed to provide configuration, enumeration and substitution of fonts to other programs (like file editor, web browser etc.).&lt;/p&gt;

&lt;p&gt;More on &lt;em&gt;fontcnfig&lt;/em&gt;, refer to &lt;a href=&quot;http://www.fangxiang.tk/2015/04/13/fontconfig/&quot;&gt;fontconfig&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;5-locale&quot;&gt;5 Locale&lt;/h1&gt;

&lt;p&gt;Locale is the last but second step responsible for displaying characters no matter of filename or file contents. FAT&apos;s &lt;em&gt;iocharset&lt;/em&gt; and NTFS&apos;s &lt;em&gt;nls&lt;/em&gt; should be set to or the Default NLS Option equals to system locale for filename display. Userspace program must support GBK (through userspace library like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libiconv&lt;/code&gt;) to decode GBK TXT file. And then your &lt;em&gt;locale&lt;/em&gt; (at least &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LC_CTYPE&lt;/code&gt;) should be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zh_CN.GBK&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Userspace X application check &lt;em&gt;locale&lt;/em&gt; and then decode the encoded filename or file content to kernel Unicode code points; those code points are then dilivered to kernel IO system for display.&lt;/p&gt;

&lt;h1 id=&quot;6-console&quot;&gt;6 Console&lt;/h1&gt;

&lt;p&gt;Above discussion still does solve Chinese filename and file content display on console.&lt;/p&gt;

&lt;p&gt;基于字符界面的控制台 console 本身并不支持点阵化字符输出，要想使之支持中文，必须将控制台切换到图形模式并加入中文解码支持。&lt;/p&gt;

&lt;p&gt;通常Linux的控制台工作在文本模式下，要想在屏幕上正确显示，汉字必须将屏幕切换到图形模式，这可以通过调用内核FrameBuffer驱动程序来实现。此外，还要能正确识别系统输出到控制台的汉字信息，并调用汉字显示模块将其输出到屏幕。&lt;/p&gt;

&lt;p&gt;一种方法是像DOS下的汉字系统所做的那样：利用系统时钟中断定时监视显存地址B800:0000处的显示缓冲区 ，动态识别缓冲区中的字符信息。这种方法要求修改内核中断和TTY驱动程序，实现起来比较困难，而且需要直接操纵硬件视频缓冲区，大大影响了系统的可移植性和稳定性。&lt;/p&gt;

&lt;p&gt;另一种方法就是UNIX下多数中文平台采用的基于伪终端（Pseudo-Terminals）的外挂式解决方案。伪终端（Pseudo-Terminal）是一种类似于终端的特殊的进程间通信通道（channel）。通道的一端被称为主设备（master pseudo-terminal device），另一端被称为从设备。写入主设备的数据被发送到从设备，而写入从设备的数据也可从主设备读出，对用户来说就好像自己实际上连接到了真正的计算机终端之上。简而言之，伪终端是位于虚拟终端和最终的终端设备之间的一种承担着输入输出转换功能的设备。&lt;/p&gt;

&lt;p&gt;伪终端诞生之初就得到了广泛应用，典型的例子是Telnet服务程序。Telnet是一种远程登录服务，用户使用Telnet客户端程序通过网络登录到远程主机之上进行各种操作。Telnet服务程序就是一个伪终端，一端连接到Telnet客户端程序，另一端连接到主机应用程序，客户和应用程序之间通过伪终端进行对话。&lt;/p&gt;

&lt;p&gt;当应用程序需要从输入设备（键盘）读入数据时，它向控制台设备（/dev/console）发出 系统调用read() ，接着内核 console 驱动响应该系统请求，从输入设备驱动程序（通常为键盘驱动keyboard.c）获得输入数据，并将之返回给应用程序。而当应用程序需要想控制台输出数据时，它通过write()系统调用将数据发送至console设备，再由内核 console 驱动转发到真正的输出设备（终端、打印机…）上去。&lt;/p&gt;

&lt;p&gt;通过以上分析可以发现如果在应用程序从控制台设备（/dev/console）读入数据之前截获键盘输入信息，并提交输入法模块处理，再将处理后得到的中英文信息发送至应用程序即可完成中文输入。而在应用程序将输出数据写入/dev/console设备之前截获输出并交由汉字识别模块处理，最终由汉字显示模块输出至屏幕，即可实现中英文输出。这就是zhcon之类的中文控制台的基本工作原理。&lt;/p&gt;

&lt;p&gt;So we need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cjktty&lt;/code&gt; patch to to the conversion.&lt;/p&gt;

&lt;h1 id=&quot;7-refs&quot;&gt;7 Refs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://tieba.baidu.com/p/2317422644&quot;&gt;iocharset和codepage有何联系和区别&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://zengrong.net/post/1019.htm&quot;&gt;关于mount/samba/字符集的两篇好文&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.crifan.com/files/doc/docbook/char_encoding/release/html/char_encoding.html&quot;&gt; 字符编码详解&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.csdn.net/wanghuiqi2008/article/details/8079071&quot;&gt;字符集编码cp936、ANSI、UNICODE&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/UTF-8&quot;&gt;UTF-8 WiKi&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-termi-hanzi/&quot;&gt;如何制造Linux虚拟终端让控制台显示中文&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;more&quot;&gt;More&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;display on X VS console, different?&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>cjktty</title>
   <link href="/2015/09/18/git-format-patch-cjktty/"/>
   <updated>2015-09-18T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/09/18/git-format-patch-cjktty</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;An alternative is Univt patch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this post, we will show how to extract &lt;em&gt;cjktty.patch&lt;/em&gt; from a patched kernel. Afterwards, we will apply the extracted patch to our own kernel. During the process, we might look into several relevant commands.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Suppose our current system kernel is 4.0.5. We will generate a &lt;em&gt;cjktty.patch&lt;/em&gt; suitable for this kernel.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The patched kernel is &lt;a href=&quot;https://github.com/Gentoo-zh/linux-cjktty&quot;&gt;linux-cjktty&lt;/a&gt; from which we will extract the desired patch.&lt;/p&gt;

    &lt;p&gt;According to past experience, &lt;em&gt;cjktty.patch&lt;/em&gt; for kernel &lt;em&gt;3.18 ~ 3.19&lt;/em&gt; fits &lt;em&gt;4.0&lt;/em&gt; as well. We will choose the branch &lt;em&gt;3.19-utf8&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Clone the chosen branch locally.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/workspace
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;nt&quot;&gt;--branch&lt;/span&gt; 3.19-utf8 &lt;span class=&quot;nt&quot;&gt;--depth&lt;/span&gt; 4 https://github.com/Gentoo-zh/linux-cjktty.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--branch&lt;/code&gt;: we only need branch 3.19-utf8. If not specified, git will clone all the branches, spending a day maybe depending on bandwidth.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--depth&lt;/code&gt;: from the repository, we find the the top 3 commits are enough to extract our &lt;em&gt;cjktty.patch&lt;/em&gt;. We MUST clone at least the top &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3 + 1 = 4&lt;/code&gt; commits.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;git log&lt;/em&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;commit 9a5a7d3215307e28df3aea6ac09931a4d55e151e
Author: microcai &amp;lt;microcai@fedoraproject.org&amp;gt;
Date:   Thu Jan 13 05:18:45 2011 +0800

    [vt] add cjk font that has 65536 chars

commit 3dbe651a011ac6b6bbd976d96b5d08fb2baf709c
Author: microcai &amp;lt;microcai@fedoraproject.org&amp;gt;
Date:   Mon Feb 21 12:58:18 2011 +0800

    [vt] diable setfont if we have cjk font in kernel

commit a2553800e3e8ea1d13f3e3a4211599a3268ce9a2
Author: microcai &amp;lt;microcaicai@gmail.com&amp;gt;
Date:   Fri Jan 9 12:45:07 2015 +0800

    [vt] fix 255 glyph limit, prepare for CJK font support

commit d8cf08a565defc2f9810b9ecd33b1b3211b029e1
Author: Greg Kroah-Hartman &amp;lt;gregkh@linuxfoundation.org&amp;gt;
Date:   Thu Mar 26 14:00:21 2015 +0100

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

    &lt;p&gt;From the output, we can see only 4 commits history as expected. We will extract the patch from the top 3 commits authored by &lt;em&gt;microcai&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Extraction&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git diff d8cf08a565defc2f9810b9ecd33b1b3211b029e1 9a5a7d3215307e28df3aea6ac09931a4d55e151e &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; cjktty.patch
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git diff HEAD~3 &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; cjktty.patch
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git format-patch HEAD~3 &lt;span class=&quot;nt&quot;&gt;--stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; cjktty.patch
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git format-patch &lt;span class=&quot;nt&quot;&gt;-3&lt;/span&gt; HEAD &lt;span class=&quot;nt&quot;&gt;--stdout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; cjktty.patch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Pay attention to the order of commit ID (SHA1 hash). Put the earliest commit ID (4th) before the latest one (HEAD).&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD~3&lt;/code&gt; means extract patch from top to 3rd commits (inclusive). The latest ID (HEAD) precedes the 3rd one.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;format-patch&lt;/em&gt; is similar to &lt;em&gt;git diff&lt;/em&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-n &amp;lt;commit&amp;gt;&lt;/code&gt; is equivalent of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;commit&amp;gt;~n&lt;/code&gt;. The patch file orgnization is a little different from that of &lt;em&gt;git diff&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;We recommend to use &lt;em&gt;format-patch&lt;/em&gt; to include commit messages, making it more appropriate for most scenarios involving exchanging patches over the Internet. Details refer to reference 1.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Test the patch&lt;/p&gt;

    &lt;p&gt;Attention please; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p [num]&lt;/code&gt; must be right, otherwise the wrong files would be patched even when no errors prompt up. Inpsect the patch file to see the pathname.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# cd /usr/src/linux/&lt;/span&gt;
   
&lt;span class=&quot;c&quot;&gt;# determine the &apos;-p&apos; option value&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# less /path/to/cjktty.patch&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# patch --verbose -p1 --dry-run &amp;lt; /path/to/cjktty.patch&lt;/span&gt;

~ &lt;span class=&quot;c&quot;&gt;# git apply --verbose --whitespace=warn -p1 --stat /path/to/cjktty.patch&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# git apply --verbose --whitespace=warn -p1 --numstat /path/to/cjktty.patch&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# git apply --verbose --whitespace=warn -p1 --check /path/to/cjktty.patch&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# git apply --verbose --whitespace=warn -p1 --summary /path/to/cjktty.patch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;When testing patch file, it might remind errors like:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Hunk #17 FAILED at 2708.
# or
error: patch failed: drivers/video/console/fbcon.c:2689
error: drivers/video/console/fbcon.c: patch does not apply
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Error number 2708 (reported by &lt;em&gt;patch&lt;/em&gt;) refers to line number in Linux-cjktty sources, while 2689 (reported by &lt;em&gt;git apply&lt;/em&gt;) in Gentoo-sources. Search 2708 or 2689 in patch file and check either/both kernel sources.&lt;/li&gt;
      &lt;li&gt;Some error are caused by extra whitespaces, especially those on &lt;em&gt;blank&lt;/em&gt; lines.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;By default, all pathnames will be patched. Sometimes, we can patch only perticular pathnames by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git apply --include &amp;lt;pattern&amp;gt;&lt;/code&gt;. &lt;em&gt;patch&lt;/em&gt; does not support this feature.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# git apply --verbose --whitespace=warn -p1 --include &apos;*myfile.lua&apos; --stat /path/to/cjktty.patch&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# git apply --verbose --whitespace=warn -p1 --include &apos;/path/to/dir&apos; --stat /path/to/cjktty.patch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Vice versa, we can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--exclude &amp;lt;pattern&amp;gt;&lt;/code&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# git apply --verbose --whitespace=warn -p1 --exclude &amp;lt;pathname-pattern&amp;gt; --stat /path/to/cjktty.patch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--include&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--exlude&lt;/code&gt; options are present, the &lt;em&gt;first match&lt;/em&gt; determines if a pathname is patched or not.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Apply the patch&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# cd /usr/src/linux/&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# patch --verbose -p1 &amp;lt; /path/to/cjktty.patch&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# git apply --verbose --whitespace=warn -p1 /path/to/cjktty.patch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We can, revert the patch by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt; option.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# cd /usr/src/linux/&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# patch --verbose -p1 --dry-run -R &amp;lt; /path/to/cjktty.patch&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# git apply --verbose --whitespace=warn -p1 --check -R /path/to/cjktty.patch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;You can reverse a patch by adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-R&lt;/code&gt; argument.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If /usr/src/linux source is polluted by patch error, you can re-install the kernel source.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;We cannot &lt;em&gt;reverse&lt;/em&gt; a patch error.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -av --unmerge gentoo-sources-4.0.5&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rm -r /usr/src/linux-4.0.5-gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -av gentoo-sources-4.0.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Pay attention to use &lt;em&gt;unmerge&lt;/em&gt; instead of &lt;em&gt;depclean&lt;/em&gt;. The former will keep package dependencies.&lt;/li&gt;
      &lt;li&gt;Maybe we can just extract the source code to &lt;em&gt;/usr/src/linux&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Reference
    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/q/32643640/2336707&quot;&gt;How to get patch files from multiple commits?&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>127.0.0.1 VS 0.0.0.0</title>
   <link href="/2015/09/14/0000-127001-localhost/"/>
   <updated>2015-09-14T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/09/14/0000-127001-localhost</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;Before a host is reachable, it must has an network interface device to which IP from ISP is assigned. That is to say, network interface undertakes networking functionalities.&lt;/li&gt;
  &lt;li&gt;On open public netwoks like &apos;Internet&apos;, usually a host is given with a IP with which a hostname is registered/associated. For example, &apos;google.com&apos; binded to its server IPs.&lt;/li&gt;
  &lt;li&gt;On some small local networks, network implementation might be narrowed to reduce complexity. So usually on a LAN, you host IP is not registered with your hostname. For example, your personal PC only gets an IP.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A host can be reached by IP from ISP. Meanwhile, every host has a special reserved IP 127.0.0.1/32 (not from ISP) bound to the loopback network interface, which works only within the host itself. So a host never reach any other host (except itself) on the network by 127.0.0.1.&lt;/p&gt;

    &lt;p&gt;Actually 127.0.0.0/8 - This block is assigned for use as the Internet host loopback address. A datagram sent by a higher-level protocol to an address anywhere within this block loops back inside the host. This is ordinarily implemented using only 127.0.0.1/32 for loopback. Addresses within the entire 127.0.0.0/8 block do not legitimately appear on any network anywhere.&lt;/p&gt;

    &lt;p&gt;The same convention is defined for computer’s that support IPv6 addressing using the connotation of ::1.&lt;/p&gt;

    &lt;p&gt;The purpose of the loopback range is testing of the TCP/IP protocol implementation on a host. Since the lower layers are short-circuited, sending to a loopback address allows the higher layers (IP and above) to be effectively tested without the chance of problems at the lower layers manifesting themselves. 127.0.0.1 is the address most commonly used for testing purposes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;We can say 127.0.0.0/8 within the bound of a host forms a tiny network which only includes the host itself. So within this tiny loopback network, the host IP is associated/registered with a loopback hostname &apos;localhost&apos;.&lt;/li&gt;
  &lt;li&gt;But usually in system, we are suggested to set another hostname like in Gentoo /etc/conf.d/hostname. As stated in item 3, this value is usually registered with IP from ISP, especially for personal PCs on LAN. Such hostname value is just a local label for the host. If unset, value in /detc/conf.d/hostname is default to &apos;localhost&apos; such that the hostname is regesitered to the tiny loopback network. Even set, you can still bind it to loopback network by adding &apos;127.0.0.1 hostname&apos; into /etc/hosts.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&quot;0.0.0.0&quot; is a valid address syntax. So it should parse as valid wherever an IP address in traditional dotted-decimal notation is expected. The all-zero value does have a special meaning. So it is &quot;valid&quot;, but has a meaning that may not be appropriate (and thus treated as not valid) for particular circumstances. It is basically the &quot;no particular address&quot; placeholder. It depends on the context of use to determine what &quot;no particular address&quot; really does.&lt;/p&gt;

    &lt;p&gt;In the context of a route entry, it usually means the default route.&lt;/p&gt;

    &lt;p&gt;In the context of servers, 0.0.0.0 means &quot;all IPv4 addresses on the local machine&quot;. If a host has two ip addresses, 192.168.1.1 and 10.1.2.1, and a server running on the host listens on 0.0.0.0, it will be reachable at both of those IPs by other hosts. At the same time, server host itself can also reach the service by 127.0.0.0/8.&lt;/p&gt;

    &lt;p&gt;The IPV6 form of 0.0.0.0 is ::0 or just ::.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;On my Gentoo, I use RDP to connect to local headless VB WinXP. The default headless listening address is 0.0.0.0 which means other host in the networks can reach the headless WinXP too.&lt;/p&gt;

    &lt;p&gt;So set it to 127.0.0.1 explicitly.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>symbolic links to config in central location</title>
   <link href="/2015/09/13/symbolic-config-file-central-location/"/>
   <updated>2015-09-13T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/09/13/symbolic-config-file-central-location</id>
   <content type="html">&lt;p&gt;&lt;em&gt;UPDATE&lt;/em&gt;: Real config files remain at where they are. Create symbolic links to them at a central place. When backup, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-L&lt;/code&gt; argument to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;There are all kinds of config files and scripts to take care of during installation or system backup. It is smart practice to put them in a central place, while creating corresponding symbolic links to them.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;mkdir /gtmisc&lt;/p&gt;

    &lt;p&gt;gtmisc is the central place to store those files.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;mv /etc/fstab /gtmisc&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;ln -sv ../gtmisc/fstab /etc/fstab&lt;/p&gt;

    &lt;p&gt;/gitmisc will store files related to root account. Repeat step 2 &amp;amp; 3 for other files.&lt;/p&gt;

    &lt;p&gt;For normal user files, you can operate like this in user home directory.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;List of files&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; /etc/fstab
 /etc/portage/{make.conf,repos.conf/,}
 /usr/local/bin/*
 /usr/local/sbin/*
 /usr/local/portage (local portage, pay attention to portage:portage ownership)
 /etc/wpa_supplicant/wpa_supplicant.conf (pay attention the file attributes)
 etc.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;gtmisc can be put anywhere you desire. But pay attention to fstab which should be accessible at the early stage of boot. For example, if gtmisc{/fstab,} were put under /home/me/gtmisc, then mount points except / in fstab would not be mounted since the mount of /home depends on /home/me/gtmisc/fstab, which forms a cyclic dependency.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Relative VS absolute symbolic link&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ln -sv /path/to/source /path/to/target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&apos;target&apos; is the symbolic link to created, pointing to &apos;source&apos; (normal files or directories).&lt;/li&gt;
      &lt;li&gt;&apos;ln&apos; command can be executed under any &apos;pwd&apos; regardless of &apos;source&apos; or &apos;target&apos; directory.&lt;/li&gt;
      &lt;li&gt;relative link: &apos;target&apos; will look for &apos;source&apos; through relative path to its own directory.&lt;/li&gt;
      &lt;li&gt;absolute link: &apos;target&apos; will look for &apos;source through absolute path.&lt;/li&gt;
      &lt;li&gt;If you move absolute link around, it still points to the correct target, while relative link would be dead.&lt;/li&gt;
      &lt;li&gt;Whether &apos;target&apos; is a relative or absolute link depends on /path/to/source.
        &lt;ol&gt;
          &lt;li&gt;If it a relative path (i.e. ln -sv ../gitmisc/fstab /etc/fstab), then target location is relative to &apos;/etc/&apos;. If you move &apos;/etc/fstab&apos; link to &apos;/home/me/fstab&apos;, the relative path will be &apos;/home/gitmisc/fstab&apos; which does not exist.&lt;/li&gt;
          &lt;li&gt;If it a absolute path (ie.e ln -sv /gitmisc/fstab /etc/fstab), then target location is at absolute path &apos;/gitmisc/fstab&apos;.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Notes
    &lt;ol&gt;
      &lt;li&gt;pvcreate, luksFormat both works on /dev/sda disk?&lt;/li&gt;
      &lt;li&gt;symbolic link relative absolute&lt;/li&gt;
      &lt;li&gt;mtab link dead&lt;/li&gt;
      &lt;li&gt;/home/zachary/gtmisc&lt;/li&gt;
      &lt;li&gt;dd boot&lt;/li&gt;
      &lt;li&gt;
        &lt;table&gt;
          &lt;tbody&gt;
            &lt;tr&gt;
              &lt;td&gt;dd if=/dev/sdb1&lt;/td&gt;
              &lt;td&gt;xz &amp;gt; boot-image-backup.xz&lt;/td&gt;
            &lt;/tr&gt;
          &lt;/tbody&gt;
        &lt;/table&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;table&gt;
          &lt;tbody&gt;
            &lt;tr&gt;
              &lt;td&gt;xzcat image-file.xz&lt;/td&gt;
              &lt;td&gt;dd of=/dev/sdb1&lt;/td&gt;
            &lt;/tr&gt;
          &lt;/tbody&gt;
        &lt;/table&gt;
      &lt;/li&gt;
      &lt;li&gt;sdb1 fat32 on windows, mounted automatically&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>LVM over LUKS over LVM</title>
   <link href="/2015/09/10/lvm-luks-lvm/"/>
   <updated>2015-09-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/09/10/lvm-luks-lvm</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;sda7&lt;/em&gt; and &lt;em&gt;sda8&lt;/em&gt; are separated by other NTFS partitions in use.&lt;/li&gt;
  &lt;li&gt;Merge them together as if they were a single partition/disk by LVM - our first LVM container.&lt;/li&gt;
  &lt;li&gt;Encrypt the new single LVM volume by DM-crypt LUKS - our LUKS container.&lt;/li&gt;
  &lt;li&gt;Create LVM volumes in LUKS container as Gentoo / and /home - our second LVM container.&lt;/li&gt;
  &lt;li&gt;LVM -&amp;gt; LUKS -&amp;gt; LVM.&lt;/li&gt;
  &lt;li&gt;No swap partition. If possible, create a swapfile instead referring to &lt;a href=&quot;http://www.fangxiang.tk/2015/03/25/gentoo-installation/&quot;&gt;swapfile&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;BOOT and EFI partitions share and reside on a USB partition, say &lt;em&gt;sdc1&lt;/em&gt;. This is different from traditional scheme.
    &lt;ol&gt;
      &lt;li&gt;The shared USB partition should be formated as FAT32 to satisfiy EFI filesystem requirement.&lt;/li&gt;
      &lt;li&gt;It should be mounted on /boot if necessary.&lt;/li&gt;
      &lt;li&gt;Make a directory &apos;EFI&apos; at root of the shared parition.&lt;/li&gt;
      &lt;li&gt;The shared USB partition is not encrypted.&lt;/li&gt;
      &lt;li&gt;You&apos;d better use &lt;em&gt;sdc2&lt;/em&gt; for the shared partition to hide it from Windows. Deatils refer to &lt;em&gt;Hide in  Windows&lt;/em&gt; next.&lt;/li&gt;
      &lt;li&gt;Encryption &amp;amp; decryption key-file is stored on USB partition as well.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Windows uses its own EFI partition on HDD, say &lt;em&gt;sda2&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Why now share boot and EFI on USB stick?
    &lt;ol&gt;
      &lt;li&gt;A single USB can now help boot many PCs and notebooks, as long as their boot information is located on the USB stick.&lt;/li&gt;
      &lt;li&gt;Kernels now stored in USB, prevent from attack online. We can unplug the USB when booting into Gentoo.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;sda7, sda8 &amp;gt; pvcreate, vgcreate (vg), lvcreate (crypt), vg-crypt &amp;gt; cryptsetup, luksOpen (cryptroot) &amp;gt; pvcreate, vgcreate (cryptvg), lvcreate (root, home), cryptvg-root &amp;amp; cryptvg-home.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;usb-preparation&quot;&gt;USB preparation&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Create shared USB partition:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# parted -a optimal /dev/sdc&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkpart primary fat32 0% 256MiB&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# set 1 boot on&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# quit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;EFI partition should be set &lt;em&gt;boot&lt;/em&gt; flag.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create FAT32 filesystem:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkfs.vfat -F32 /dev/sdc1&lt;/span&gt;
or
&lt;span class=&quot;c&quot;&gt;# busybox mkfs.vfat /dev/sdc1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;USB shared partition is not encrypted. If you put the shared partition within the LVM-LUKS-LVM architecture, then you need add LUKS support to Grub2.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;key-file&quot;&gt;key-file&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Preparations&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkdir /mnt/sdc1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount /dev/sdc1 /mnt/sdc1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkdir /mnt/sdc1/luks-gnupg-key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Generate GPG-encrypted key-file:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dd &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/urandom &lt;span class=&quot;nv&quot;&gt;bs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;8388607 &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 | gpg &lt;span class=&quot;nt&quot;&gt;--symmetric&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cipher-algo&lt;/span&gt; AES256 &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; ~/luks-gnupg-key.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;LiveDVD &lt;em&gt;root&lt;/em&gt; acount does not support this command as &lt;em&gt;gpg 2&lt;/em&gt; need GUI popup to prompt password. Switch to normal user account in LiveDVD.&lt;/p&gt;

    &lt;p&gt;Without explici mark &apos;$&apos;, all commands are executed under &lt;em&gt;root&lt;/em&gt; account in LiveDVD.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Save key-file to USB stick:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; ~/luks-gnupg-key.gpg /mnt/sdc1/luks-gnupg-key/
&lt;span class=&quot;c&quot;&gt;# umount /mnt/sdc1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The gpg-encrypted key-file is stored on the shared USB for booting. You can store it in other media though unnecessary and tedious.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Decrypt key-file for temporal usage:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--decrypt&lt;/span&gt; ~/luks-gnupg-key.gpg &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ~/luks-gnupg-key
&lt;span class=&quot;c&quot;&gt;# cp /home/gentoo/luks-gnupg-key .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This temporary decrypted key-file is used in root account. Don&apos;t expose decrypted key-file online or to anyone.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;sda7--sda8-preparation&quot;&gt;&lt;em&gt;sda7&lt;/em&gt; &amp;amp; &lt;em&gt;sda8&lt;/em&gt; preparation&lt;/h1&gt;

&lt;p&gt;On &lt;em&gt;sda&lt;/em&gt;, find the separated free space:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# parted -a optimal /dev/sda&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# unit s&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkpart primary START END&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# name 7 &apos;Gentoo partition&apos;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkpart primary START END&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# name 8 &apos;Gentoo partition&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;START and END should exactly be the right &lt;em&gt;sector&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Otherwise, other partitions in use would be ruined! Take &lt;em&gt;/dev/sda7&lt;/em&gt; for example, its previous ancestor partition &lt;em&gt;/dev/sda4&lt;/em&gt;&apos;s last sector/unit is &lt;em&gt;100000000s&lt;/em&gt;. Then the START of &lt;em&gt;/dev/sda7&lt;/em&gt; must be &lt;em&gt;100000001s&lt;/em&gt;. Remember to &lt;strong&gt;PLUS ONE&lt;/strong&gt;. We can verify this by examine other successive partitions in use.&lt;/p&gt;

    &lt;p&gt;If possible, resort to percentage like 0% or 100%.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We don&apos;t create filesystem &lt;em&gt;ext4&lt;/em&gt; on &lt;em&gt;sda7&lt;/em&gt; or &lt;em&gt;sda8&lt;/em&gt; directly since they are treated as underlying container: LVM -&amp;gt; LUKS -&amp;gt; LVM.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;1st-lvm-container&quot;&gt;1st LVM container&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# pvcreate /dev/sda7 /dev/sda8&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vgcreate vg /dev/sda7 /dev/sda8&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lvcreate -l 100%FREE vg -name crypt&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# pvdisplay / vgdisplay / lvdisplay / lvscan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;pvcreate&lt;/em&gt; is optional since &lt;em&gt;vgcreate&lt;/em&gt; will automatically create PVs on &lt;em&gt;sda7&lt;/em&gt; and &lt;em&gt;sda8&lt;/em&gt; if needed.&lt;/li&gt;
  &lt;li&gt;We can find /&lt;em&gt;dev/vg&lt;/em&gt; directory created.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Now, &lt;em&gt;sda7&lt;/em&gt; and &lt;em&gt;sda8&lt;/em&gt; is merged as a single LVM device &lt;em&gt;/dev/mapper/vg-crypt&lt;/em&gt; or &lt;em&gt;/dev/vg/crypt&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Each time you create a LVM in VG, a new mapper device will be created &lt;em&gt;/dev/mapper/&lt;/em&gt;. The mapper device name will be &apos;VG name + LV name&apos;. This mapper device is actually a simbolic link. Similarly, /&lt;em&gt;dev/vg/crypt&lt;/em&gt; is also a symbolic linking to the same destination as &lt;em&gt;/dev/mapper/vg-crypt&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;However, when booting into Gentoo, these mapper device will be real device file.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Try to use &lt;em&gt;pvdisplay&lt;/em&gt;, &lt;em&gt;vgdisplay&lt;/em&gt;, &lt;em&gt;lvdisplay&lt;/em&gt;, &lt;em&gt;lvscan&lt;/em&gt; etc. anytime to get information.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;luks-container&quot;&gt;LUKS container&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cryptsetup --cipher serpent-xts-plain64 --key-size 512 --hash sha512 --key-file /home/gentoo/luks-gnupg-key luksFormat /dev/mapper/vg-crypt&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cryptsetup --key-file /home/gentoo/luks-gnupg-key luksAddKey /dev/mapper/vg-crypt&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cryptsetup luksOpen /dev/mapper/vg-crypt cryptroot&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cryptsetup luksDump /dev/mapper/vg-crypt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Create LUKS container. Try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cryptsetup luksDump /dev/mapper/vg-crypt&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To add a fallback LUKS passphrase, just in case we lost the key-file. According to current experience, passphrase needs less time. This passphrase is different from the one used to encrypt key-file above.&lt;/p&gt;

    &lt;p&gt;We must provide the the previous key-file or passphrase before adding a LUKS key slot. Attention, we use the decrypted key-file instead of the encrypted one since &lt;em&gt;root&lt;/em&gt; account cannot pop up box for decryption.&lt;/p&gt;

    &lt;p&gt;Up to now, &lt;em&gt;/dev/mapper/vg-crypt&lt;/em&gt; is protected by both LUKS key-file (gpg-encrypted) and passphrase. We have achieved &lt;strong&gt;full disk encrytion&lt;/strong&gt;. Try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cryptsetup luksDump /dev/mapper/vg-crypt&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Treat &lt;em&gt;vg-crypt&lt;/em&gt; as a normal disk partition which is encrypted by DM-crypt LUKS. To make use of it, we have to decrypt it first. Here, we use the fallback passphrase to decrypt. It is faster.&lt;/p&gt;

    &lt;p&gt;When &lt;em&gt;vg-crypt&lt;/em&gt; is decrypted, we also get a mapper device &lt;em&gt;/dev/mapper/cryptroot&lt;/em&gt;. The device name can be set freely at your desire.&lt;/p&gt;

    &lt;p&gt;We can now treat the decrypted device as another normal disk partition, on which we will create our 2nd LVM container.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;why-2nd-lvm-container&quot;&gt;Why 2nd LVM container?&lt;/h1&gt;

&lt;p&gt;This question can be narrowed down to: why need LVM over LUKS?&lt;/p&gt;

&lt;p&gt;A decrypted LUKS device like &lt;em&gt;/dev/mapper/cryptroot&lt;/em&gt; should&apos;d better be regarded as a partition instead of a disk (like &lt;em&gt;/dev/sdb&lt;/em&gt;). So command like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parted -a optimal /dev/mapper/cryptroot&lt;/code&gt; is NOT encouraged. It is complicated to make use of partitions created directly over LUKS device.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;What if I take only part of &lt;em&gt;/dev/mapper/cryptroot&lt;/em&gt; to install Gentoo, while leaving the rest for NTFS data or even another system Arch Linux?&lt;/li&gt;
  &lt;li&gt;What if I separate &lt;em&gt;/home&lt;/em&gt;, &lt;em&gt;/usr&lt;/em&gt;, &lt;em&gt;/tmp&lt;/em&gt; etc. mount points?&lt;/li&gt;
  &lt;li&gt;What if I want to adjust Gentoo&apos;s storage?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Of course, we can prepare Gentoo installation on this decrypted LUKS partition directly if don&apos;t care above issues:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkfs &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; ext4 /dev/mapper/cryptroot
mount &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; ext4 /dev/mapper/cryptroot /mnt/gentoo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sometime, we can also re-format &lt;em&gt;/dev/mapper/cryptroot&lt;/em&gt; for other usage like re-installing Gentoo.&lt;/p&gt;

&lt;p&gt;With LVM over LUKS we unlock all the partitions (LVM volumes) by one key-file / passphrase, and easily resize volums without the hassle work above. For example, you want to extend &lt;em&gt;/&lt;/em&gt; size while reducing &lt;em&gt;/home&lt;/em&gt; size.&lt;/p&gt;

&lt;p&gt;If you&apos;re going to simply dump everything on a single partition (which is totaly fine with some setups), there is no point of 2nd LVM container. However, if you want to have several volumes, LVM will make it more convenient and easier to use, and this is why many people go after &apos;LVM over LUKS&apos;.&lt;/p&gt;

&lt;p&gt;If you really don&apos;t like the 2nd LVM but need separate &lt;em&gt;/&lt;/em&gt;, &lt;em&gt;/home&lt;/em&gt;, etc. Please &lt;em&gt;lvcreate&lt;/em&gt; LVM volumes directly over the 1st LVM container. After that, &lt;em&gt;cryptsetup&lt;/em&gt; them repsectively with LUKS key-files or passphrases. What a nightmare!&lt;/p&gt;

&lt;p&gt;Refer to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://forums.gentoo.org/viewtopic-t-1028630.html&quot;&gt;luks without lvm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://forums.gentoo.org/viewtopic-t-1028448-highlight-.html&quot;&gt;LUKS over LVM or LVM over LUKS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system&quot;&gt;dm-crypt/Encrypting an entire system&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;2nd-lvm-container&quot;&gt;2nd LVM container&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# pvcreate /dev/mapper/cryptroot&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vgcreate cryptvg /dev/mapper/cryptroot&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lvcreate --size 25G --name root cryptvg&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lvcreate --extents 100%FREE --name home cryptvg&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# pvdisplay / vgdisplay / lvdisplay&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Like in the 1st LVM container, this step is optional.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;/dev/cryptvg/&lt;/em&gt; directory created.&lt;/li&gt;
  &lt;li&gt;Create LVM &lt;em&gt;root&lt;/em&gt; device as &lt;em&gt;/&lt;/em&gt; mount point.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create LVM &lt;em&gt;home&lt;/em&gt; device as &lt;em&gt;/home&lt;/em&gt; mount point.&lt;/p&gt;

    &lt;p&gt;Wee will see &lt;em&gt;cryptvg-root&lt;/em&gt; and &lt;em&gt;cryptvg-home&lt;/em&gt; symbolic links under &lt;em&gt;/dev/mapper&lt;/em&gt;. Similarly, &lt;em&gt;/dev/cryptvg{/root, /home}&lt;/em&gt; links created as well.&lt;/p&gt;

    &lt;p&gt;Up to now, we have finished the basic LVM -&amp;gt; LUKS -&amp;gt; LVM architecture. We will install Gentoo over the newly created devices of 2nd LVM.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;format-gentoo-partitions&quot;&gt;Format Gentoo partitions&lt;/h1&gt;

&lt;p&gt;When we say &lt;em&gt;format sdxy as ext4&lt;/em&gt;, we actually means &lt;em&gt;create ext4 filesystem on sdxy&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkfs.ext4 -L &quot;root&quot; /dev/mapper/cryptvg-root&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkfs.ext4 -m 0 -L &quot;home&quot; /dev/mapper/cryptvg-home&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;BOOT and EFI share USB partition &lt;em&gt;/dev/sdc1&lt;/em&gt; (VFAT).&lt;/p&gt;

&lt;h1 id=&quot;mount-gentoo-partitions&quot;&gt;Mount Gentoo partitions&lt;/h1&gt;

&lt;p&gt;During &lt;em&gt;mount&lt;/em&gt; and &lt;em&gt;umount&lt;/em&gt;, try &lt;em&gt;lsblk&lt;/em&gt;, &lt;em&gt;blkid&lt;/em&gt; etc.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mount -v -t ext4 /dev/mapper/cryptvg-root /mnt/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkdir -v /mnt/gentoo/{home,boot}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t ext4 /dev/mapper/cryptvg-home /mnt/gentoo/home&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# umount -v /dev/sdc1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t vfat /dev/sdc1 /mnt/gentoo/boot&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkdir /mnt/gentoo/boot/EFI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The directory name could be upper case &apos;EFI&apos; or lower case &apos;efi&apos;. Currently, &apos;EFI&apos; works fine.&lt;/p&gt;

&lt;h1 id=&quot;stage-tarbar&quot;&gt;stage tarbar&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd /mnt/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# tar xvjpf /path/to/stage3-amd64-20150319.tar.bz2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;chroot&quot;&gt;Chroot&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# vgchange -a y vg, VG name can be ommited.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cryptsetup luksOpen /dev/mapper/vg-crypt cryptroot, you could use key-file to decrypt vg-crypt as well.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vgchange -a y vgcryptvg&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t ext4 /dev/mapper/cryptvg-root /mnt/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t ext4 /dev/mapper/cryptvg-home /mnt/gentoo/home&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t vfat /dev/sdc1 /mnt/gentoo/boot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you return to LiveDVD and try to chroot again, please execute the above six commands first. Then follow:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cp -v -L /etc/resolv.conf /mnt/gentoo/etc/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t proc proc /mnt/gentoo/proc2&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v --rbind /sys /mnt/gentoo/sys&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v --rbind /dev /mnt/gentoo/dev&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v --make-rslave /mnt/gentoo/sys&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v --make-rslave /mnt/gentoo/dev&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# chroot /mnt/gentoo /bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# source /etc/profile &amp;amp;&amp;amp; export PS1=&quot;(chroot) $PS1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;p&gt;Refer to &lt;a href=&quot;2015-03-25-gentoo-installation.md&quot;&gt;Gentoo Installation&lt;/a&gt; and &lt;a href=&quot;2015-08-15-gentoo-over-lvm-luks.md&quot;&gt;gentoo over lvm luks&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Try to restore some config backup files like &apos;make.conf&apos;, &apos;fstab&apos;, &apos;wpa_supplicant.conf&apos;, &apos;.bashrc&apos; &apos;repos.conf/{gentoo.conf, layman.conf, local.conf} etc.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Of the most important, the fundamental difference is &apos;Grub2&apos; and &apos;genkernel initramfs&apos;.&lt;/p&gt;

    &lt;p&gt;Follow steps below.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;difference&quot;&gt;Difference&lt;/h1&gt;

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

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;sys-kernel/genkernel cryptsetup&quot; &amp;gt; /etc/portage/package.use/genkernel&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -av genkernel&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# genkernel --lvm --luks --gpg --busybox --install initramfs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Don&apos;t worry about &lt;em&gt;–gpg&lt;/em&gt; problem occured in LiveDVD above. genkernell will compile GnuPG 1 instead of 2.&lt;/p&gt;

&lt;h2 id=&quot;grub2&quot;&gt;Grub2&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# grub-install --target=x86_64-efi --efi-directory=/boot --boot-directory=/boot --bootloader-id=Grub2 --removable --modules=part\_gpt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--bootloader-id=Grub2&lt;/code&gt; and &lt;em&gt;/dev/sdc&lt;/em&gt; (USB stick) might be optional.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--efi-directory&lt;/code&gt; specifies the mountpoint of the ESP (i.e. the USB &lt;em&gt;sdc1&lt;/em&gt; is mounted at &lt;em&gt;/boot&lt;/em&gt;). It replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--root-directory&lt;/code&gt; which is deprecated.&lt;/li&gt;
  &lt;li&gt;No need to append &lt;em&gt;/dev/sdc&lt;/em&gt; since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--efi-directory=&lt;/code&gt; is enough. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSTALL_DEVICE&lt;/code&gt; parameter of &lt;em&gt;grub-install&lt;/em&gt; is mainly for BIOS boot.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://forums.gentoo.org/viewtopic-p-7011836.html&quot;&gt;EFI boot with GRUB2 on amd64, dual boot with Windows7 x64&lt;/a&gt; and &lt;a href=&quot;https://wiki.gentoo.org/wiki/GRUB2/zh-CN&quot;&gt;grub2 zh-CN&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;kernel-and-init-arguments&quot;&gt;Kernel and init arguments&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# */etc/default/grub*:

GRUB_CMDLINE_LINUX=&quot;crypt_root=UUID=&apos;of /dev/mapper/vg-crypt&apos; dolvm root=UUID=&apos;of /dev/mapper/cryptvg-root&apos; rootfstype=ext4 root_keydev=PARTUUID=&apos;of boot and EFI shared partition&apos; root_key=/relative/path/to/luks-gnupg-key-file&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;crypt_root: the UUID of the partition which is encrypted by DM-crypt LUKS. In our case, this is LVM volume /dev/mapper/vg-crypt or /dev/vg/crypt.&lt;/li&gt;
  &lt;li&gt;dolvm: activate LVM volumes on bootup. This needs support from LVM support in initramfs.&lt;/li&gt;
  &lt;li&gt;root: the real / mount point for Gentoo. In our case, it is /dev/mapper/cryptvg-root or /dev/cryptvg/root.&lt;/li&gt;
  &lt;li&gt;rootfstype: Gentoo root filesystem.&lt;/li&gt;
  &lt;li&gt;root_keydev: the device where DM-crypt LUKS key-file is stored. In our case, it is boot and EFI partition on USB stick. Always prefer PARTUUID over UUID on a GPT disk.&lt;/li&gt;
  &lt;li&gt;root_key: the path to DM-crypt LUKS key-file. The value should be relative path to root_keydev mount point.&lt;/li&gt;
  &lt;li&gt;You can use device file name or use UUID instead for those arguments. It&apos;s free choince.&lt;/li&gt;
  &lt;li&gt;The 2nd reference adds a parameter &apos;target=cryptroot&apos; whose usage is unclear. Don&apos;t try this if not sure.&lt;/li&gt;
  &lt;li&gt;Refer to man page of &lt;em&gt;genkernel&lt;/em&gt; for those parameters. They can be set to device name or the device UUID/PARTUUID.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;lvmetad-service&quot;&gt;lvmetad service&lt;/h2&gt;

&lt;p&gt;After getting into new Gentoo system, &lt;em&gt;grub-mkconfig&lt;/em&gt; might complain about &lt;em&gt;lvmetad&lt;/em&gt; issue which does NO harm. If you really want to get rid of the warning, just run &lt;em&gt;rc-service lvmetad start&lt;/em&gt; before &lt;em&gt;grub-mkconfig&lt;/em&gt; and remember to stop afterwards.&lt;/p&gt;

&lt;h2 id=&quot;generating-grub2-menu&quot;&gt;Generating Grub2 menu&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# grub-mkconfig -o /boot/grub/grub.cfg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In chroot, grub-mkconfig might fail to probe (by calling os-prober) Windows on HDD. When getting into Gentoo, execute it again to make up.&lt;/p&gt;

&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;

&lt;p&gt;In our scheme, boot and EFI shared partition is not encrypted. If it is encrypted by LUKS too, we need more configurations. Read &lt;a href=&quot;https://wiki.gentoo.org/wiki/GRUB2/AdvancedStorage&quot;&gt;Grub2 advanced storage&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;get-out-of-chroot&quot;&gt;Get out of chroot&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;exit&lt;/li&gt;
  &lt;li&gt;umount -lv /mnt/gentoo/home&lt;/li&gt;
  &lt;li&gt;umount -lv /mnt/gentoo/boot&lt;/li&gt;
  &lt;li&gt;umount -lv /mnt/gentoo/dev{/shm,/pts,}&lt;/li&gt;
  &lt;li&gt;umount -lv /mnt/gentoo{/proc,/sys,}&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;vgchange -a n cryptvg&lt;/p&gt;

    &lt;p&gt;Should give the VG name.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;cryptsetup luksClose cryptroot&lt;/li&gt;
  &lt;li&gt;vgchange -a n vg&lt;/li&gt;
  &lt;li&gt;reboot&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;boot--efi-image-backuprestore&quot;&gt;boot &amp;amp; EFI image backup/restore&lt;/h1&gt;

&lt;h2 id=&quot;dd&quot;&gt;&lt;em&gt;dd&lt;/em&gt;&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;dd&lt;/em&gt; copies bit by bit, free space included.&lt;/li&gt;
  &lt;li&gt;Be careful on &lt;em&gt;if&lt;/em&gt; and &lt;em&gt;of&lt;/em&gt; argument.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# dd if=/dev/sdb2 | xz &amp;gt; boot-image-backup.xz&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# xzcat image-file.xz | dd of=/dev/sdb2, restore from backup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;tar&quot;&gt;&lt;em&gt;tar&lt;/em&gt;&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# tar -cvjpf /media/Misc/boot-image-backup.tar.bz2 /boot&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# tar -xvjpf /media/Misc/boot-image-backup.tar.bz2 -C /boot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;j&lt;/em&gt; can be replaced with &lt;em&gt;z&lt;/em&gt; or &lt;em&gt;J&lt;/em&gt;to create &lt;em&gt;.gz&lt;/em&gt; or &lt;em&gt;.xz&lt;/em&gt; backup.&lt;/li&gt;
  &lt;li&gt;Avoid `/&apos; after &lt;em&gt;boot&lt;/em&gt;, namely &lt;em&gt;/boot&lt;/em&gt; instead of &lt;em&gt;/boot/&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;operations-to-usb-sdc1&quot;&gt;Operations to USB sdc1&lt;/h1&gt;

&lt;p&gt;From the installation process, we find for sdc1, we only:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Copy the LUKS key there;&lt;/li&gt;
  &lt;li&gt;grub-install command;&lt;/li&gt;
  &lt;li&gt;grub-mkconfig;&lt;/li&gt;
  &lt;li&gt;Mount sdc1 as /boot in /etc/fstab&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If data ruined in sdc1 or anything else undesirable happend, just repeat step 1-4 as long as LUKS key-file or fall-back passphrase exist.&lt;/p&gt;

&lt;h1 id=&quot;hide-in--windows&quot;&gt;Hide in  Windows&lt;/h1&gt;

&lt;p&gt;The current USB is 1 GiB in size which only part of is needed for boot and EFI. So we could make use of the remaining around 750MiB for usual USB data storage.&lt;/p&gt;

&lt;p&gt;We create the shared partition /dev/sdc1 formated as FAT32. However, what if this USB is inserted into Windows? Enverything in /dev/sdc1 will be exposed as normal USB stick, the luks-gnupg-key included.&lt;/p&gt;

&lt;p&gt;Hence we would like to achieve:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Make use of remaining 750MiB capacity.&lt;/li&gt;
  &lt;li&gt;Hide the shared partition from Windows.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For 1, we just need to create a new partition on the remaining free space. For 2, please note that windows WILL NOT SHOW BOTH PARTITIONS OF USB at the same time. One partition will be hidden and another will be visible. Technically, Windows allocates a drive letter to only single partition on a USB drive. However on linux operating system both partitions will be visible without any problem.&lt;/p&gt;

&lt;p&gt;So a better idea is to use sdc1 as the normal data storage partition, while sdc2 for the shared partition. It would be:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Number  Start   End     Size   File system  Name             Flags
 1      1049kB  752MB   751MB  ntfs         USB stick
 2      752MB   1002MB  251MB  fat32        Gentoo boot EFI  boot, esp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;sdc1 now is formated as ntfs&lt;/em&gt;. If it was formated as mkfs.vfat (fat32), then UEFI firmware would NOT recognize sdc2 as the shared partition for system boot.&lt;/p&gt;

&lt;p&gt;At real practice, you&apos;d best not use sdc1 for data storage just in case for operation mistake to ruin sdc2.&lt;/p&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://tahirzia.wordpress.com/2012/11/20/how-to-create-a-separate-hidden-boot-partition-on-usb/&quot;&gt;how-to-create-a-separate-hidden-boot-partition-on-usb/&lt;/a&gt; and &lt;a href=&quot;https://forums.gentoo.org/viewtopic-t-1028800.html&quot;&gt;hide from windows&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;http://www.ms.unimelb.edu.au/~trice/linux/tricks/luksresize/&lt;/li&gt;
  &lt;li&gt;http://manual.aptosid.com/en/hd-install-crypt-en.htm&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system&quot;&gt;dm-crypt/Encrypting an entire system&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;notes-1&quot;&gt;Notes&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;deselect=y notifyd? what is the point? weechat&lt;/li&gt;
  &lt;li&gt;noatime in fstab&lt;/li&gt;
  &lt;li&gt;cjktty patch&lt;/li&gt;
  &lt;li&gt;remember to: libtool finsih&lt;/li&gt;
  &lt;li&gt;list of files need backup&lt;/li&gt;
  &lt;li&gt;os-probe will find Windows In Gentoo.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>TeXLive Gentoo</title>
   <link href="/2015/08/29/texlive-gentoo/"/>
   <updated>2015-08-29T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/08/29/texlive-gentoo</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#abcs&quot; id=&quot;markdown-toc-abcs&quot;&gt;ABCs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#2015-to-2016&quot; id=&quot;markdown-toc-2015-to-2016&quot;&gt;2015 to 2016&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#texlive-packages&quot; id=&quot;markdown-toc-texlive-packages&quot;&gt;TeXLive packages&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#fontconfig&quot; id=&quot;markdown-toc-fontconfig&quot;&gt;Fontconfig&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#enable-texlive-fonts&quot; id=&quot;markdown-toc-enable-texlive-fonts&quot;&gt;Enable TeXLive fonts&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#chinese&quot; id=&quot;markdown-toc-chinese&quot;&gt;Chinese&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Before anything else, read &lt;a href=&quot;https://www.tug.org/texlive/doc/texlive-en/texlive-en.html#x1-80002&quot;&gt;2 Overview of TEX Live&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Read &lt;a href=&quot;/2015/02/05/LaTeX/&quot;&gt;LaTeX&lt;/a&gt; on TeX &lt;em&gt;engine&lt;/em&gt; and &lt;em&gt;format&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# echo &quot;app-text/texlive xetex cjk l10n_zh science publishers&quot; &amp;gt; /etc/portage/package.use/texlive&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt app-text/texlive&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt font-adobe-100dpi font-adobe-75dpi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;xetex&lt;/em&gt; is compatible with Fontconfig.&lt;/p&gt;

    &lt;p&gt;XeTeX includes xeCJK macro package which invokes XeTeX engin to compile Chinese TeX files.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(opt) &lt;em&gt;cjk&lt;/em&gt; draws in CJK (&lt;em&gt;dev-texlive/texlive-langcjk&lt;/em&gt; and &lt;em&gt;dev-tex/cjk-latex&lt;/em&gt;)&lt;/p&gt;

    &lt;p&gt;The old CJK macro script requires more user involvement.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;l10n_zh&lt;/em&gt; (&lt;em&gt;dev-texlive/texlive-langchinese&lt;/em&gt;)&lt;/p&gt;

    &lt;p&gt;CTeX extends and depends on CJK, thus making Chinese TeX compiling much easier.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;USE flags like &lt;em&gt;extra&lt;/em&gt; depend on a world of packages many of which are unnecessary. If you are sure, just install what we need on the fly.&lt;/p&gt;

    &lt;p&gt;Specially, &lt;em&gt;publishers&lt;/em&gt; and &lt;em&gt;science&lt;/em&gt; USE is useful when you write conference papers like IEEE, ACM etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Many TeXLive packages depends on 100dpi and 75dpi bitmap fonts.&lt;/li&gt;
  &lt;li&gt;TeXLive layout &lt;em&gt;/etc/texmf/web2c/texmf.cnf&lt;/em&gt;, &lt;em&gt;/usr/share/texmf-dist/web2c/texmf.cnf&lt;/em&gt; and &lt;em&gt;/etc/texmf/texmf.d/05searchpaths.cnf&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;2015-to-2016&quot;&gt;2015 to 2016&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avtC --deselect=n $(qlist -IC texlive)&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -av1 app-text/texlive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you are upgrading TeXLive, follow &lt;a href=&quot;https://wiki.gentoo.org/wiki/Project:TeX/Tex_Live_Migration_Guide&quot;&gt;Tex Live Migration Guide&lt;/a&gt; and &lt;a href=&quot;https://wiki.gentoo.org/wiki/Upgrading_TeXLive&quot;&gt;Upgrading TeXLive&lt;/a&gt; first.&lt;/p&gt;

&lt;h2 id=&quot;texlive-packages&quot;&gt;TeXLive packages&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;app-text/texlive&lt;/em&gt; defines installtion configuration while &lt;em&gt;app-text/texlive-core&lt;/em&gt;, &lt;em&gt;dev-texlive/texlive-basic&lt;/em&gt;, &lt;em&gt;dev-libs/kpathsea&lt;/em&gt; and &lt;em&gt;web2c&lt;/em&gt; thereof consists of real sources. Separate TeXLive packages (i.e. &lt;em&gt;dev-tex/biblatex&lt;/em&gt;, &lt;em&gt;dev-tex/cjk-latex&lt;/em&gt; etc.) will go to TEXMFSITE (&lt;em&gt;/usr/share/texmf-site&lt;/em&gt;) which is Gentoo-specific directory. This allows for more unitary upgrades or security fixes.&lt;/p&gt;

&lt;p&gt;Use &lt;em&gt;app-portage/pfl&lt;/em&gt; to search online repository locating specific package files.&lt;/p&gt;

&lt;p&gt;We can also &lt;em&gt;manually&lt;/em&gt; put TeXLive packages into TEXMFHOME or TEXMFLOCAL without &lt;em&gt;portage&lt;/em&gt; management. By convention, we put personal macro files or packages into TEXMFHOME.&lt;/p&gt;

&lt;p&gt;For example, for &lt;em&gt;biblatex&lt;/em&gt; (superior to &lt;em&gt;natbib&lt;/em&gt;) support:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -av1 dev-tex/biblatex-3.7-r1&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt dev-tex/biber-2.7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Versions &lt;em&gt;&amp;lt;dev-tex/biblatex-3.7-r1&lt;/em&gt; would block &lt;em&gt;dev-texlive/texlive-plaingeneric-2017&lt;/em&gt;. Make sure sub versions (&lt;em&gt;*.5&lt;/em&gt;, &lt;em&gt;*.7&lt;/em&gt;, &lt;em&gt;*.10&lt;/em&gt; etc.) of &lt;em&gt;biblatex&lt;/em&gt; and &lt;em&gt;biber&lt;/em&gt; should match.&lt;/p&gt;

&lt;p&gt;Since verion over 2.0, &lt;em&gt;biblatex&lt;/em&gt; package use &lt;em&gt;biber&lt;/em&gt; (superior to &lt;em&gt;bibtex&lt;/em&gt;) as te default backend:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt dev-tex/biber&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We could change it to TeXLive default &lt;em&gt;bibtex&lt;/em&gt; in TeX source file. Read &lt;a href=&quot;http://tex.stackexchange.com/a/25702&quot;&gt;bibtex-vs-biber-and-biblatex-vs-natbib&lt;/a&gt; on bibliography.&lt;/p&gt;

&lt;h1 id=&quot;fontconfig&quot;&gt;Fontconfig&lt;/h1&gt;

&lt;p&gt;Though CTeX makes use of Fontconfig fonts directly, we need to make sure the fonts name are correctly resolved between Fontconfig and TeX. Check what you have:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fc-list :lang&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;zh-cn | &lt;span class=&quot;nb&quot;&gt;sort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Edit &lt;em&gt;/usr/share/texmf-dist/tex/latex/ctex/fontset/ctex-xecjk-winfonts.def&lt;/em&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-tex&quot; data-lang=&quot;tex&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;% ctex-xecjk-winfonts.def: Windows 的 xeCJK 字体设置，默认为六种中易字体&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;% vim:ft=tex&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\setCJKmainfont&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[BoldFont={NotoSansHans-Bold},ItalicFont={AdobeKaitiStd-Regular}]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;AdobeFangsongStd-Regular&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKsansfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;NotoSansHans-DemiLight&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKmonofont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;AdobeSongStd-Light&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\setCJKfamilyfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;zhsong&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;AdobeSongStd-Light&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKfamilyfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;zhhei&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;NotoSansHans-Bold&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKfamilyfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;zhkai&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;AdobeKaitiStd-Regular&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKfamilyfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;zhfs&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;AdobeFangsongStd-Regular&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;% \setCJKfamilyfont{zhli}{LiSu}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;% \setCJKfamilyfont{zhyou}{YouYuan}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\newcommand*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\songti&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\CJKfamily&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;zhsong&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;% 宋体&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\newcommand*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\heiti&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\CJKfamily&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;zhhei&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;   &lt;span class=&quot;c&quot;&gt;% 黑体&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\newcommand*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\kaishu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\CJKfamily&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;zhkai&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;% 楷书&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\newcommand*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\fangsong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\CJKfamily&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;zhfs&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;% 仿宋&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;% \newcommand*{\lishu}{\CJKfamily{zhli}}    % 隶书&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;% \newcommand*{\youyuan}{\CJKfamily{zhyou}} % 幼圆&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\endinput&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Remove extra &lt;em&gt;square braces&lt;/em&gt;. For setCJKmonofont, just use a normal 宋体 since all Chinese characters are monospace (single and same width).&lt;/p&gt;

&lt;p&gt;XeTeX can resolve Fontconfig fonts by &lt;em&gt;font file name&lt;/em&gt; apart from &lt;em&gt;font (family) name&lt;/em&gt;. We should set OSFONTDIR varaible then. Details refer to &lt;a href=&quot;/2015/02/03/TeXLive-2014-Ubuntu-Installation/&quot;&gt;TeXLive Ubuntu&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;enable-texlive-fonts&quot;&gt;Enable TeXLive fonts&lt;/h2&gt;

&lt;p&gt;There are many free fonts shipped with TeXLive. For XeTeX, they must be enabled in Fontconfig first:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# eselect fontconfig list&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eselect fontconfig enable 09-texlive.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;chinese&quot;&gt;Chinese&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;CTeX by default requires XeTeX (&lt;em&gt;xelatex&lt;/em&gt; binary) egnine.&lt;/li&gt;
  &lt;li&gt;Current stable TeXLive-2014 still requires &lt;em&gt;ctex-xecjk-winfonts.def&lt;/em&gt;. Update font names there as above.&lt;/li&gt;
  &lt;li&gt;Due to a &lt;a href=&quot;http://bbs.ctex.org/forum.php?mod=viewthread&amp;amp;tid=78821&quot;&gt;bug&lt;/a&gt; of &lt;em&gt;xdvipdfmx&lt;/em&gt;, &quot;Noto Sans S Chinese&quot; (思源黑体) is garbled. Update to TeXLive-2015 or apply the patch.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>iOS Linux</title>
   <link href="/2015/08/24/ios-linux/"/>
   <updated>2015-08-24T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/08/24/ios-linux</id>
   <content type="html">&lt;p&gt;How to mount iOS and transfer files to Iphone?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Installation&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ $ echo &quot;gnome-base/gvfs ios fuse&quot; &amp;gt;&amp;gt; /etc/portage/package.use/gvfs, *fuse* is optional
user@tux ~ $ emerge -av1 gvfs
user@tux ~ $ emerge -avt usbmuxd
user@tux ~ $ usbmuxd -f -v (opt), automatically invoked when iOS device plugged in
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Restart X and login as a normal user account.&lt;/li&gt;
  &lt;li&gt;Thunar will remind you to &lt;a href=&quot;https://ubuntuforums.org/showthread.php?t=1861617&amp;amp;page=4&amp;amp;p=11531339#post11531339&quot;&gt;unlock passcode NO.31&lt;/a&gt; in Iphone. Iphone might ask you to trust the computer. Just do it.&lt;/li&gt;
  &lt;li&gt;If you &lt;a href=&quot;https://askubuntu.com/a/447416&quot;&gt;cannot find&lt;/a&gt; &lt;em&gt;Documents on XXX&apos;s iPhone&lt;/em&gt; in Thunar, restart iPhone.&lt;/li&gt;
  &lt;li&gt;If &lt;em&gt;fuse&lt;/em&gt; USE is enabled, documents can be accessed under &lt;em&gt;/var/run/user/1000/gvfs/&lt;/em&gt; or &lt;em&gt;$HOME/.gvfs/&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Refs:
    &lt;ol&gt;
      &lt;li&gt;https://wiki.gentoo.org/wiki/Apple_iPod,_iPad,_iPhone&lt;/li&gt;
      &lt;li&gt;https://wiki.archlinux.org/index.php/IPod&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>VirtualBox</title>
   <link href="/2015/08/21/virtualbox/"/>
   <updated>2015-08-21T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/08/21/virtualbox</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#terminology&quot; id=&quot;markdown-toc-terminology&quot;&gt;Terminology&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#schema&quot; id=&quot;markdown-toc-schema&quot;&gt;Schema&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#windows-xp-32-bit-vm&quot; id=&quot;markdown-toc-windows-xp-32-bit-vm&quot;&gt;Windows XP 32-bit VM&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#start-vm-with-vrde&quot; id=&quot;markdown-toc-start-vm-with-vrde&quot;&gt;Start VM with VRDE&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#manage-vms-on-command-line&quot; id=&quot;markdown-toc-manage-vms-on-command-line&quot;&gt;Manage VMs on Command Line&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#guest-os-configurations&quot; id=&quot;markdown-toc-guest-os-configurations&quot;&gt;Guest OS Configurations&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#usb-supoort&quot; id=&quot;markdown-toc-usb-supoort&quot;&gt;USB Supoort&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#host-only-networking&quot; id=&quot;markdown-toc-host-only-networking&quot;&gt;Host-only networking&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ide-drive-port-limit&quot; id=&quot;markdown-toc-ide-drive-port-limit&quot;&gt;IDE Drive Port Limit&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#delete-vm&quot; id=&quot;markdown-toc-delete-vm&quot;&gt;Delete VM&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#windows-embedded-standard-7-x86-vm&quot; id=&quot;markdown-toc-windows-embedded-standard-7-x86-vm&quot;&gt;Windows Embedded Standard 7 x86 VM&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#android-x86-vm&quot; id=&quot;markdown-toc-android-x86-vm&quot;&gt;Android-x86 VM&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#arch-linux-x86_64-vm&quot; id=&quot;markdown-toc-arch-linux-x86_64-vm&quot;&gt;Arch Linux x86_64 VM&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#virtualbox-guestadditions&quot; id=&quot;markdown-toc-virtualbox-guestadditions&quot;&gt;VirtualBox GuestAdditions&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#virtualbox-sharedfolder&quot; id=&quot;markdown-toc-virtualbox-sharedfolder&quot;&gt;VirtualBox sharedfolder&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#expand-vdi-size&quot; id=&quot;markdown-toc-expand-vdi-size&quot;&gt;Expand VDI Size&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#centos-82-amd64&quot; id=&quot;markdown-toc-centos-82-amd64&quot;&gt;CentOS 8.2 Amd64&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#references&quot; id=&quot;markdown-toc-references&quot;&gt;References&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This post indroduces installing VirtualBox in Gentoo host.&lt;/p&gt;

&lt;h1 id=&quot;terminology&quot;&gt;Terminology&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Host OS&lt;/p&gt;

    &lt;p&gt;Operating system where VMM runs.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Guest OS&lt;/p&gt;

    &lt;p&gt;Operating system runs over VirtualBox.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;VirtualBox&lt;/p&gt;

    &lt;p&gt;A virtual machine manager (VMM) owned by Orcale, also named as &lt;em&gt;Base package&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Once installed, it will insert VirtualBox kernel modules into the host OS, like &lt;em&gt;vboxdrv&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Oracle VM VirtualBpx Extension Packs&lt;/p&gt;

    &lt;p&gt;A proprietary bundle of packages that extends the functionality of the Base Package, like USB 3.0, VirtualBox Remote Desktop Protocol (VRDP), webcam etc.&lt;/p&gt;

    &lt;p&gt;Extension Packs is optional. However, if you choose to install, then make sure it has the same version as the Base Package.&lt;/p&gt;

    &lt;p&gt;Similar to the Base, Package, Extension Packs also presents as kernel modules on host OS, like &lt;em&gt;vboxnetadp&lt;/em&gt; and &lt;em&gt;vboxnetflt&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Oracle VM VirtualBox GuestAdditions&lt;/p&gt;

    &lt;p&gt;Package to be installed &lt;em&gt;inside&lt;/em&gt; the guest OS that optimizes performance and usability, like mouse pointer integration, shared folders, shared clipboard, seamless windows, time synchroniation with host OS etc.&lt;/p&gt;

    &lt;p&gt;GuestAdditions also serve as kernel modules but in guest OS, like &lt;em&gt;vboxsf&lt;/em&gt;, &lt;em&gt;vboxvideo&lt;/em&gt;, and &lt;em&gt;vboxguest&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Make sure relevant versions match.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;VirtualBox. Versions of Base Package, Extension Packs and GuestAdditions must match.&lt;/li&gt;
      &lt;li&gt;Guest OS. Kernel modules are built against the &lt;em&gt;current&lt;/em&gt; kernel. When VirtualBox is upgraded, kernel modules on host OS is re-built automatically. However, if guest OS kernel is changed, we should re-build the guest kernel modules manually (i.e. GuestAdditions).&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;VirtualBox depends on QT as GUI. But I would like a XFCE4 desktop without any QT packages. QT related USE flags are disabled in Gentoo &lt;em&gt;make.conf&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;So I will emerge VirtualBox without GUI. To manage VMs, resort to CLI.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;USEs&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# echo &quot;app-emulation/virtualbox headless additions extensions&quot; &amp;gt; /etc/portage/package.use/virtualbox&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;headless&lt;/em&gt; builds VirtualBox without any graphic frontend.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;em&gt;attitions&lt;/em&gt; for Guest Addtitions.&lt;/p&gt;

        &lt;p&gt;Since VirtualBox 5, this USE is removed. Emerge &lt;em&gt;app-emulation/virtualbox-additions&lt;/em&gt; manually.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;em&gt;extension&lt;/em&gt; for Extension Packs.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Build&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt app-emulation/virtualbox&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt app-emulation/virtualbox-additions (&amp;gt;=5)&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt app-emulation/virtualbox-extpack-oracle (&amp;gt;=5)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;It reminds accepting PUEL licence. Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/VirtualBox&quot;&gt;VirtualBox wiki&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;If fail to emerge VirtualBox, then probably you should bump to a newer version. Lastest Linux kernel usually requires lastest VirtualBox.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Group - vboxusers&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# gpasswd -a &amp;lt;username&amp;gt; vboxusers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Add current &lt;em&gt;username&lt;/em&gt; to &lt;em&gt;vboxusers&lt;/em&gt; group. Refer to in &lt;a href=&quot;/2017/12/12/wireshark/&quot;&gt;newgrp in Wireshark post&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Kernel modules&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# modinfo vboxdrv vboxnetadp vboxnetflt vboxpci&lt;/span&gt;
root@tux / &lt;span class=&quot;c&quot;&gt;# modprobe -v vboxdrv vboxnetadp vboxnetflt vboxpci&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;If you launch VirtualBox frequently, add these modules to &lt;em&gt;/etc/conf.d/modules&lt;/em&gt; for automatic loading on boot.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;vboxdrv&lt;/em&gt; is the core module for host OS and must always be present. &lt;em&gt;vboxnetadp&lt;/em&gt; and &lt;em&gt;vboxnetflt&lt;/em&gt; are required for any VM networking beyond the default NAT mode (i.e. host-only, bridged etc.).&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;When booting into a new Linux kernel (i.e kernel upgrading), you could no longer load modules like &lt;em&gt;vobxdrv&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# modprobe vboxdrv&lt;/span&gt;
modprobe: FATAL: Module vboxdrv not found.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Read the first reference on &lt;em&gt;Kernel driver not installed&lt;/em&gt; section. The solution is to rebuild VirtualBox external modules:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt1 app-emulation/virtualbox-modules&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt1 @module-rebuild&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;More details in &lt;a href=&quot;/2015/03/25/gentoo-installation/&quot;&gt;Upgrade kernel to unstable 4.0.0&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Up to now everyting related to VirtualBox VMM is prepared on host OS. Next is to create VM through CLI.&lt;/p&gt;

    &lt;p&gt;On &lt;a href=&quot;2020/10/12/macos.md&quot;&gt;macOS&lt;/a&gt;, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew cask&lt;/code&gt; to install &lt;em&gt;virtualbox&lt;/em&gt; and &lt;em&gt;virtualbox-extension-pack&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Remove quotes around sysmbol &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; and symbol &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/udev/rules.d

# Correct /dev/{vboxdrv,vboxdrvu,vboxnetctl} permissions to 0600
KERNEL==&quot;vboxdrv&quot;, NAME=&quot;vboxdrv&quot;, OWNER=&quot;root&quot;, GROUP=&quot;vboxusers&quot;, MODE=&quot;0660&quot;
KERNEL==&quot;vboxdrvu&quot;, NAME=&quot;vboxdrvu&quot;, OWNER=&quot;root&quot;, GROUP=&quot;vboxusers&quot;, MODE=&quot;0660&quot;
KERNEL==&quot;vboxnetctl&quot;, NAME=&quot;vboxnetctl&quot;, OWNER=&quot;root&quot;,GROUP=&quot;vboxusers&quot;, MODE=&quot;0660&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;To load the new rule, execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;udevadm trigger&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;schema&quot;&gt;Schema&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Avoid 64-bit guest OS. 64-bit OS occupies one third more resources (disk, memory) than the 32-bit version. What was worse, it seems &lt;em&gt;VBoxGuestAddtions-amd64.exe&lt;/em&gt; makes no difference on the guest (double mouse, weird resolution etc.).&lt;/li&gt;
  &lt;li&gt;The less snapshots we create, the better is the performance.&lt;/li&gt;
  &lt;li&gt;Put VDI file on host&apos;s home partition for better performance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;windows-xp-32-bit-vm&quot;&gt;Windows XP 32-bit VM&lt;/h1&gt;

&lt;p&gt;VM won&apos;t even start without QT GUI support. But VRDP helps! VRDP is a replacement of QT GUI!&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;First create VM with VirtualBox CLI;&lt;/li&gt;
  &lt;li&gt;Enable VRDP support for VM;&lt;/li&gt;
  &lt;li&gt;Connect to headless VM by VRDP client FreeRDP.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href=&quot;https://www.virtualbox.org/manual/ch07.html#idm3213&quot;&gt;VBoxManage createvm&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage list ostypes
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage createvm &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; WinXP32 &lt;span class=&quot;nt&quot;&gt;--ostype&lt;/span&gt; WindowsXP &lt;span class=&quot;nt&quot;&gt;--register&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--basefolder&lt;/span&gt; ~/Documents/VirtualBox/Machines
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VboxManage list vms
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage registervm ~/Documents/VirtualBox/Machines/WinXP32/WinXP32.vbox &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;opt&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; vboxmanage list vms
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage modifyvm WinXP32 &lt;span class=&quot;nt&quot;&gt;--memory&lt;/span&gt; 384 &lt;span class=&quot;nt&quot;&gt;--acpi&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--nic1&lt;/span&gt; nat &lt;span class=&quot;nt&quot;&gt;--nictype1&lt;/span&gt; Am79C973 &lt;span class=&quot;nt&quot;&gt;--audio&lt;/span&gt; alsa &lt;span class=&quot;nt&quot;&gt;--audiocontroller&lt;/span&gt; ac97 &lt;span class=&quot;nt&quot;&gt;--usb&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--usbehci&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--vrde&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--vrdeaddress&lt;/span&gt; 127.0.0.1 &lt;span class=&quot;nt&quot;&gt;--vrdeport&lt;/span&gt; 5001,5010-5012 &lt;span class=&quot;nt&quot;&gt;--clipboard&lt;/span&gt; bidirectional
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage createmedium &lt;span class=&quot;nt&quot;&gt;--filename&lt;/span&gt; ~/Documents/VirtualBox/Machines/WinXP32/WinXP32.vdi &lt;span class=&quot;nt&quot;&gt;--size&lt;/span&gt; 5000 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;omitted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storagectl WinXP32 &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;IDE Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; ide &lt;span class=&quot;nt&quot;&gt;--controller&lt;/span&gt; PIIX4
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach WinXP32 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;IDE Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; hdd &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; ~/Documents/VirtualBox/Machines/WinXP32/WinXP32.vdi
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach WinXP32 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;IDE Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; hdd &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; /path/to/ISO &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;omitted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach WinXP32 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;IDE Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; dvddrive &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; /usr/share/virtualbox/VBoxGuestAdditions.iso &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;or &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; additions&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage sharedfolder add WinXP32 &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; WLshare &lt;span class=&quot;nt&quot;&gt;--hostpath&lt;/span&gt; /media/Misc/VMs/WLshare
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, I re-use an existing &lt;em&gt;.vdi&lt;/em&gt; instead of guest installation ISO, thus avoiding guest OS installing process. Apparently, &lt;em&gt;createmedium&lt;/em&gt; prodecure is omitted.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;ostypes&lt;/p&gt;

    &lt;p&gt;List supported OSes. I am going to install &lt;em&gt;Windows XP 32-bit&lt;/em&gt;. The value is &lt;em&gt;WindowsXP&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;createvm
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--name&lt;/code&gt; should be enclosed by double quotes in case of white spaces.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--register&lt;/code&gt; to register the VM instantly, or run &lt;em&gt;VBoxManage registervm&lt;/em&gt; afterwards.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--basefoler&lt;/code&gt; can be used to specify this VM&apos;s files location (i.e. set to NTFS partition). If not set, it will default to &lt;em&gt;${HOME}/.VirtualBox/Machines&lt;/em&gt; which is different from VirtualBox confiuration file.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;registervm&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Bug&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--register&lt;/code&gt; of &lt;em&gt;createvm&lt;/em&gt; failed to register the VM though it reports negtive success. Possible solutions:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Specifically add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--basefolder&lt;/code&gt; to &lt;em&gt;createvm –register&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Pass &lt;em&gt;full&lt;/em&gt; path of &lt;em&gt;.vbox&lt;/em&gt; file to &lt;em&gt;registervm&lt;/em&gt; on a separate shell command.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;modifyvm
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--nictype1 Am79C973&lt;/code&gt; sets virtual Ethernet hardware to AMD PCNet FAST III (Am79C973). VirtualBox 5 now use Intel PRO/1000 T Server (82543GC) as default, which requires extra drivers installed.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--audio alsa&lt;/code&gt; could be &lt;em&gt;pulse&lt;/em&gt; instead.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--vrde on&lt;/code&gt; is to enable VRDP support thus I can remotely connect to the VM by RDP client.&lt;/li&gt;
      &lt;li&gt;` –usb on –usbehci on&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; enables USB 1.0 and 2.0. To enable 3.0, use &lt;/code&gt;–usbxhci on`.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--vrdeaddress&lt;/code&gt; set to loopback address. If unset, it binds to all host network interfaces accepting both IPv4 and IPv6. Refer to &lt;a href=&quot;/2015/09/14/0000-127001-localhost/&quot;&gt;127.0.0.1 vs 0.0.0.0&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--draganddrop&lt;/code&gt; option is useful if you need it. However, it is vunerable to security issue.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;storagectl&lt;/p&gt;

    &lt;p&gt;Set disk controller for VM. Don&apos;t use SATA related controller for &lt;em&gt;WindowsXP&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;storageattach VDI&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;WinXP32.vdi&lt;/em&gt; is copied from some guy in QQ group, getting rid of installing VM OS from scratch.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;storageattach&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;VBoxGuestAddiontions.iso&lt;/em&gt; supports file sharing, mouse switch etc between &lt;em&gt;host&lt;/em&gt; and &lt;em&gt;guest&lt;/em&gt;. WE will install this toolbox after entering &lt;em&gt;WindowsXP&lt;/em&gt; VM.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;sharedfolder&lt;/p&gt;

    &lt;p&gt;Create a folder for share on host and mount it on guest.&lt;/p&gt;

    &lt;p&gt;After entering VM, open Windows Explorer and look for it under &quot;My Networking Places&quot;, &quot;Entire Network&quot;, &quot;VirtualBox Shared Folders&quot;, &quot;\\Vboxsvr&quot;.&lt;/p&gt;

    &lt;p&gt;By right-clicking on a shared folder and selecting &quot;Map network drive&quot; from the menu that pops up, you can assign a drive letter to that shared folder.&lt;/p&gt;

    &lt;p&gt;If you don&apos;t assign a drive letter, each time to access the shared, we have to find it under &quot;\\Vboxsvr&quot;.&lt;/p&gt;

    &lt;p&gt;If you cannot locate the shared folder under Windows Explorer/Network, check if Network Discovery is turned on in Control Panel (default for Home networking type). You can also try CMD:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;net use z: \\vboxsvr\WLshare
# or
net use z: \\vboxsrv\WLshare
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Up to now, the VM is prepared! We need a RDP client.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;start-vm-with-vrde&quot;&gt;Start VM with VRDE&lt;/h2&gt;

&lt;p&gt;VirtualBox Remote Display Protocol (VRDP) is a backwards-compatible extension to Microsoft&apos;s Remote Desktop Protocol (RDP). VirtualBox Remote Desktop Extension (VRDE) is an Oracle VRDP implementation. Apart from TCP/Ports and TCP/Address, we have:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--vrdemulticon on&lt;/code&gt; allows multiple simultaneous connections to the same VM, without which we can resort to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--vrdereusecon on&lt;/code&gt; that can cut off the current connection for the new one.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--vrdeauthtype external&lt;/code&gt; requires username and password of the host before connection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is FreeRDP setup details:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Up to now, the VM is created! But VirtualBox does not have QT GUI. We need RDP client, i.e. FreeRDP.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt net-misc/freerdp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;startvm&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage startvm &lt;span class=&quot;s2&quot;&gt;&quot;WinXP32&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; headless
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxHeadless &lt;span class=&quot;nt&quot;&gt;--startvm&lt;/span&gt; WinXP32
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;VBoxHeadless&lt;/em&gt; is a tool the launch VM as a server mode without GUI. If you buy a VPS, the OS mostly runs in a similar mode (maybe VNC browser). Now the VM is started, but not showing up! We need to use FreeRDP to get X.&lt;/p&gt;

    &lt;p&gt;On MacOS host, the GUI mode may &lt;a href=&quot;https://forums.virtualbox.org/viewtopic.php?f=8&amp;amp;t=99676&quot;&gt;report error&lt;/a&gt;:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;You must specify a machine to start, using the command line.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Please disable Audio is guest VM setting. You may also want to read &lt;a href=&quot;https://forums.virtualbox.org/viewtopic.php?f=8&amp;amp;t=95041&quot;&gt;VirtualBox crashes after upgrading to macOS Catalina&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;FreeRDP&lt;/p&gt;

    &lt;p&gt;The RDP TCP port is set to an optional list &lt;em&gt;5001,5010-5012&lt;/em&gt; (default &lt;em&gt;3389&lt;/em&gt;).&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;xfreerdp +clipboard /w:1024 /h:576 /v:127.0.0.1:5001
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;The server IP is &lt;em&gt;vrdeaddress&lt;/em&gt;, NOT IP of &lt;em&gt;guest&lt;/em&gt;. Since I connect to VM locally, so it &lt;em&gt;127.0.0.1&lt;/em&gt;. &lt;em&gt;xfreerdp&lt;/em&gt; can add many other parameters, like window size, audio, video etc.&lt;/li&gt;
      &lt;li&gt;&apos;Ctrl + Alt + Enter&apos; to toggle full screen.&lt;/li&gt;
      &lt;li&gt;You might found there are two mouse pointers, one for &lt;em&gt;host&lt;/em&gt; while another for &lt;em&gt;guest&lt;/em&gt;. Also the screen resolution is not correctly set. Install &lt;em&gt;VBoxGuestAdditions&lt;/em&gt; we&apos;ve attached the Vm. Open file explorer, installer is located in partition &lt;em&gt;(D:) VirtualBox GuestAdditions&lt;/em&gt;, &lt;em&gt;VBoxWindowsAdditions.exe&lt;/em&gt;. Disable &lt;em&gt;Direct3D&lt;/em&gt; component on a low end VM.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Shutdown&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage controlvm WinXP32 savestate/acpipowerbutton/poweroff/pause
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;pause&lt;/em&gt;: temporarily puts a virtual machine on hold, without changing its state for good. The VM window will be painted in gray to indicate that the VM is currently paused.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;poweroff&lt;/em&gt;: has the same effect on a virtual machine as pulling the power cable on a real computer. Again, the state of the VM is not saved beforehand, and data may be lost. (This is equivalent to selecting the &quot;Close&quot; item in the &quot;Machine&quot; menu of the GUI or pressing the window&apos;s close button, and then selecting &quot;Power off the machine&quot; in the dialog.)&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;savestate&lt;/em&gt;: saves the current state of the VM to disk and then stop the VM. (This is equivalent to selecting the &quot;Close&quot; item in the &quot;Machine&quot; menu of the GUI or pressing the window&apos;s close button, and then selecting &quot;Save the machine state&quot; in the dialog.) We can think &lt;em&gt;savestate&lt;/em&gt; as suspend to disk (&lt;em&gt;hibernate&lt;/em&gt;).&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;acpipowerbuttion&lt;/em&gt;: simulates long press the PC&apos;s power buttion to shutdown directly without saving.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Which to use, depens on:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;If jobs in VM is not yet finished (like editing a file), use &lt;em&gt;savestate&lt;/em&gt;;&lt;/li&gt;
      &lt;li&gt;If every jobs completed, use &lt;em&gt;acpipoweroff&lt;/em&gt; (as long as ACPI is enabled for VM) or &lt;em&gt;poweroff&lt;/em&gt;;&lt;/li&gt;
      &lt;li&gt;If still want to leave the VM running remotely, just close the RDP window.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Remove guest addtions ISO&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach WinXP32 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;IDE Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; dvddrive &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; emptydrive / none
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Detach ISO file after &lt;em&gt;VBoxGuestAddtions&lt;/em&gt; is installed.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;manage-vms-on-command-line&quot;&gt;Manage VMs on Command Line&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Load kernel modules.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;m &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;vbox&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;drv,netadp,netflt,pci&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;modprobe &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done
&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;VirtualBox modules loaded!&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Startup script.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;PS3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;Please enter your choice on VM WinXP32: &apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;startvm&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;rdp&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;poweroff&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;acpipowerbutton&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;savestate&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;quit&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;select &lt;/span&gt;opt &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;do
    case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$opt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;startvm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;you choose to launch WinXP32&quot;&lt;/span&gt;
        VBoxHeadless &lt;span class=&quot;nt&quot;&gt;--startvm&lt;/span&gt; WinXP32
        &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;rdp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;you choose to connect WinXP32&quot;&lt;/span&gt;
        xfreerdp +clipboard /sound /f /v:127.0.0.1:5001
        &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;acpipowerbutton&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;you chose to acpipowerbuttion WinXP32&quot;&lt;/span&gt;
        VBoxManage controlvm WinXP32 poweroff
        &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;savestate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;you chose to save WinXP32state&quot;&lt;/span&gt;
        VBoxManage controlvm WinXP32 savestate
        &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;poweroff&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;you chose to poweroff WinXP32&quot;&lt;/span&gt;
        VBoxManage controlvm WinXP32 poweroff
        &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;quit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;invalid option&apos;&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;guest-os-configurations&quot;&gt;Guest OS Configurations&lt;/h2&gt;

&lt;p&gt;After getting into the Windows XP system, we can adjust some system configurations to minimize resource consumption:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;For English OS, then set &lt;em&gt;non-Unicode&lt;/em&gt; language to &lt;em&gt;Chinese&lt;/em&gt; and set the &lt;em&gt;Regional Options&lt;/em&gt; values.&lt;/li&gt;
  &lt;li&gt;Disable &lt;em&gt;soundman&lt;/em&gt; etc. with &lt;em&gt;msconfig&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Set &lt;em&gt;Wireless Zero Configuration&lt;/em&gt;, &lt;em&gt;Windows Audio&lt;/em&gt;, &lt;em&gt;Windows Themes&lt;/em&gt; etc. services to &lt;em&gt;Disabled&lt;/em&gt; or &lt;em&gt;Manual&lt;/em&gt;. Refer to &lt;a href=&quot;http://blog.sciencenet.cn/blog-76534-508692.html&quot;&gt;Windows XP 终极优化&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;If installed &apos;迅雷&apos;, then set &lt;em&gt;XLServicePlatform&lt;/em&gt; to &lt;em&gt;Manual&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;My Computer, Properties, Advanced, Performance, Settings, Adjust for best performance.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;usb-supoort&quot;&gt;USB Supoort&lt;/h2&gt;

&lt;p&gt;Attach plugged in USB device to VM. First set the USB version to 1.0, 2.0 or 3.0 for VM.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vboxmanage list usbhost
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vboxmanage controlvm WinXP32 usbattach USB-UUID
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vboxmanage list usbhost
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vboxmanage controlvm WinXP32 usbdetach USB-UUID
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Find the USB device UUID by checking the Manufacture and Product field. Make sure the Current State field is Available.&lt;/li&gt;
  &lt;li&gt;Attach the USB to VM.&lt;/li&gt;
  &lt;li&gt;The Current State field becomes Captured (by VM).&lt;/li&gt;
  &lt;li&gt;Detach from VM.&lt;/li&gt;
  &lt;li&gt;Get UUID from &lt;em&gt;vboxmanage list usbhost&lt;/em&gt; instead of &lt;em&gt;blkid&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can also make this attachment &lt;em&gt;permanent&lt;/em&gt; by creating a &lt;em&gt;usbfilter&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;host-only-networking&quot;&gt;Host-only networking&lt;/h2&gt;

&lt;p&gt;Take &lt;a href=&quot;#android-x86&quot;&gt;Android-x86&lt;/a&gt; for example, the very first step is to create a &lt;em&gt;hostonlyif&lt;/em&gt; interface, as follows:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage hostonlyif create/remove vboxnet0
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ip &lt;span class=&quot;nb&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; VBoxManage list hostonlyifs
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage hostonlyif ipconfig vboxnet0 &lt;span class=&quot;nt&quot;&gt;--ip&lt;/span&gt; 192.168.56.1 &lt;span class=&quot;c&quot;&gt;# &apos;--dhcp&apos; is not supported currently&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage modifyvm Android51 &lt;span class=&quot;nt&quot;&gt;--nic2&lt;/span&gt; hostonly &lt;span class=&quot;nt&quot;&gt;--hostonlyadapter2&lt;/span&gt; vboxnet0
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage dhcpserver add/modify &lt;span class=&quot;nt&quot;&gt;--ifname&lt;/span&gt; vboxnet0 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--netname&lt;/span&gt; HostInterfaceNetworking-vboxnet0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--ip&lt;/span&gt; 192.168.56.1 &lt;span class=&quot;nt&quot;&gt;--netmask&lt;/span&gt; 255.255.255.0 &lt;span class=&quot;nt&quot;&gt;--lowerip&lt;/span&gt; 192.168.56.100 &lt;span class=&quot;nt&quot;&gt;--upperip&lt;/span&gt; 192.168.56.110 &lt;span class=&quot;nt&quot;&gt;--enable&lt;/span&gt;
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage list dhcpservers
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ip address
&lt;span class=&quot;c&quot;&gt;# boot Android51&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# netcfg eth1 dhcp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Check &lt;em&gt;iptables&lt;/em&gt; and/or firewall.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -I INPUT 4 -i vboxnet0 -s 192.168.56.0/24 -j ACCEPT&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -I OUTPUT 4 -o vboxnet0 -s 192.168.56.0/24 -j ACCEPT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Apart from NAT/bridged networking, we can use &lt;em&gt;iptables redirect&lt;/em&gt; to let &lt;em&gt;vboxnet0&lt;/em&gt; traffic go outside.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Especially, guest VM can share host&apos;s proxy as long as it&apos;s listening on &lt;em&gt;local network&lt;/em&gt; (i.e. &lt;em&gt;0.0.0.0&lt;/em&gt;). You may want to prohibit LAN devices connection to proxy.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -I INPUT 4 -i vboxnet0 -d 192.168.56.0/24 -p tcp -m tcp --dport 1080 -j DROP&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -I INPUT 4 -i vboxnet0 -d 192.168.56.0/24 -p udp -m udp --dport 1080 -j DROP (opt)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Share host proxy&lt;/p&gt;

    &lt;p&gt;Alternatively, &lt;em&gt;iptables redirect vboxnet0&lt;/em&gt; traffic to &lt;em&gt;127.0.0.1&lt;/em&gt; like:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ # iptables -t nat -A PREROUTING [ -s 192.168.56.101 ] -d 192.168.56.100 -i vboxnet0 -p tcp -m tcp --dports 1080,9050 -j DNAT --to-destination 127.0.0.1
user@tux ~ # sysctl -w net.ipv4.conf.vboxnet0.route_localnet=0 (runtime)
# or 
user@tux ~ # sysctl -p /etc/sysctl.d/15-route_localnet.conf
#
net.ipv4.conf.vboxnet0.route_localnet = 1 (better)
net.ipv4.conf.all.route_localnet = 1 (dangerous)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;By default, kernel &lt;a href=&quot;https://security.stackexchange.com/a/137603&quot;&gt;refuses to route&lt;/a&gt; from source or to destination loopback addresses (i.e. 127.0.0.1). &lt;em&gt;vboxnet0&lt;/em&gt; interface would not be created before VirtualBox launches. So &lt;em&gt;15-route_localnet.conf&lt;/em&gt; does not apply accross boot.&lt;/p&gt;

    &lt;p&gt;A more general method is enabling &lt;em&gt;net.ipv4.ip_forward&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;c&quot;&gt;# sysctl -w net.ipv4.ip_forward=1&lt;/span&gt;
user@tux ~ &lt;span class=&quot;c&quot;&gt;# iptables -A FORWARD -i vboxnet0 -o vboxnet0 -j ACCEPT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;On MacOS, the &lt;em&gt;vboxnet0&lt;/em&gt; interface is not created automatically, we need to create manually like that of Android-x86 above.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;IF the host OS or the guest OS is Windows system, then Host-only refuses connection.&lt;/p&gt;

    &lt;p&gt;Either &lt;em&gt;turn on network discovery&apos; or use security policy *secpol.msc&lt;/em&gt; to set &lt;em&gt;Unidentified network&lt;/em&gt; as &lt;em&gt;Private&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;ide-drive-port-limit&quot;&gt;IDE Drive Port Limit&lt;/h2&gt;

&lt;p&gt;Windows XP &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--port 2 --device 0&lt;/code&gt; refuses to attach extra ISO:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;VBoxManage: error: No drive attached to device slot 0 on port 2 of controller &apos;IDE Controller&apos;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Windows XP guest uses IDE PIIX4 disk drive that supports at most 2 ports. Each port supports two devices , namely (0, 0), (0, 1), (1, 0) and (1, 1). If you have a strong reason to use port 2, then create SATA disk drive like Win 7 guest.&lt;/p&gt;

&lt;p&gt;Especially, each port of SATA disk drive only supports one device, namely (0, 0), (1, 0), (2, 0) etc.&lt;/p&gt;

&lt;h2 id=&quot;delete-vm&quot;&gt;Delete VM&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vboxmanage list vms
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;vboxmanage unregistervm WinXP32 &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Amost everything related to the VM is deleted, especially the virtual disk image file (&lt;em&gt;.vdi&lt;/em&gt;), snapshots, saved state files, VM xml file etc.&lt;/p&gt;

&lt;h1 id=&quot;windows-embedded-standard-7-x86-vm&quot;&gt;Windows Embedded Standard 7 x86 VM&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage list ostypes &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;Windows7&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage createvm &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; WES7x86 &lt;span class=&quot;nt&quot;&gt;--ostype&lt;/span&gt; Windows7 &lt;span class=&quot;nt&quot;&gt;--register&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--basefolder&lt;/span&gt; ~/Documents/VirtualBox/Machines
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage registervm ~/Documents/VirtualBox/Machines/WES7x86/WES7x86.vbox &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;opt&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage modifyvm WES7x86 &lt;span class=&quot;nt&quot;&gt;--memory&lt;/span&gt; 700 &lt;span class=&quot;nt&quot;&gt;--audio&lt;/span&gt; alsa &lt;span class=&quot;nt&quot;&gt;--audiocontroller&lt;/span&gt; hda &lt;span class=&quot;nt&quot;&gt;--acpi&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--vrde&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--vrdeproperty&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TCP/Ports=5001,5010-5012&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--vrdeproperty&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TCP/Address=127.0.0.1&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--clipboard&lt;/span&gt; bidirectional &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--draganddrop&lt;/span&gt; bidirectional &lt;span class=&quot;nt&quot;&gt;--usb&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--usbehci&lt;/span&gt; on, &lt;span class=&quot;nt&quot;&gt;--nic1&lt;/span&gt; bridged &lt;span class=&quot;nt&quot;&gt;--bridgeadapter1&lt;/span&gt; wlp3s0, &lt;span class=&quot;nt&quot;&gt;--nic1&lt;/span&gt; nat, &lt;span class=&quot;nt&quot;&gt;--boot1&lt;/span&gt; dvd &lt;span class=&quot;nt&quot;&gt;--boot2&lt;/span&gt; disk &lt;span class=&quot;nt&quot;&gt;--boot3&lt;/span&gt; none &lt;span class=&quot;nt&quot;&gt;--boot4&lt;/span&gt; none&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage createmedium &lt;span class=&quot;nt&quot;&gt;--filename&lt;/span&gt; ~/Documents/VirtualBox/Machines/WES7x86/WES7x86.vdi &lt;span class=&quot;nt&quot;&gt;--size&lt;/span&gt; 7000 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;createhd&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storagectl WES7x86 &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; sata &lt;span class=&quot;nt&quot;&gt;--controller&lt;/span&gt; IntelAHCI &lt;span class=&quot;nt&quot;&gt;--portcount&lt;/span&gt; 3 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;SATA and Intel AHCI&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach WES7x86 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; hdd &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; ~/Documents/VirtualBox/Machines/WES7x86/WES7x86.vdi
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach WES7x86 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; dvddrive &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; /media/Misc/WLshare/en_windows_embedded_standard_7_runtime_x86_dvd_521803.iso
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach WES7x86 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; dvddrive &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; /usr/share/virtualbox/VBoxGuestAdditions.iso
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage sharedfolder add WES7x86 &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; WLshare &lt;span class=&quot;nt&quot;&gt;--hostpath&lt;/span&gt; /media/Misc/WLshare
&lt;span class=&quot;c&quot;&gt;# Installation processing ...&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach WES7x86 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; dvddrive &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; emptydrive
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach WES7x86 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; dvddrive &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; none
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For details on choosing template and components during installation, read the Windows post.&lt;/p&gt;

&lt;p&gt;Since the ISO image is till attached to SATA Controller, booting will be directed to installation process again. Either update VM boot order or F12 at early phase.&lt;/p&gt;

&lt;p&gt;There is no sound in WES7x86 guest. Please change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--audiocontroller&lt;/code&gt; to &lt;a href=&quot;https://www.virtualbox.org/manual/ch03.html#ftn.idm1540&quot;&gt;Intel &lt;em&gt;hda&lt;/em&gt; instead of default &lt;em&gt;ac97&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;android-x86-vm&quot;&gt;Android-x86 VM&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage createvm &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; Android51 &lt;span class=&quot;nt&quot;&gt;--ostype&lt;/span&gt; Linux26 &lt;span class=&quot;nt&quot;&gt;--register&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--basefolder&lt;/span&gt; /media/Misc/VirtualBox/Machines
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage modifyvm Android51 &lt;span class=&quot;nt&quot;&gt;--memory&lt;/span&gt; 700 &lt;span class=&quot;nt&quot;&gt;--acpi&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--mouse&lt;/span&gt; usbtablet &lt;span class=&quot;nt&quot;&gt;--usb&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--usbehci&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--vrde&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--vrdeproperty&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TCP/Ports=5001,5010-5012&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--vrdeproperty&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TCP/Address=127.0.0.1&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--clipboard&lt;/span&gt; bidirectional
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage createmedium &lt;span class=&quot;nt&quot;&gt;--filename&lt;/span&gt; /media/Misc/VirtualBox/Machines/Android51/Android51.vdi &lt;span class=&quot;nt&quot;&gt;--size&lt;/span&gt; 4000
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storagectl Android51  &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;IDE Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; ide &lt;span class=&quot;nt&quot;&gt;--controller&lt;/span&gt; PIIX4
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach Android51 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;IDE Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; hdd &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; /media/Misc/VirtualBox/Machines/Android51/Android51.vdi
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach Android51 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;IDE Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; dvddrive &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; ~/Downloads/cm-x86-13.0-r1.iso
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage list vms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Installation - Install Android-x86 to harddisk.&lt;/li&gt;
  &lt;li&gt;Create/Modify partitions.&lt;/li&gt;
  &lt;li&gt;Do you want to use GPT? No!&lt;/li&gt;
  &lt;li&gt;New - Primary - Bootable - Write - &lt;em&gt;yes&lt;/em&gt; - Quit.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;sda1&lt;/em&gt; unkown VBOX HARDDISK.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;ext3/ext4&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Format &lt;em&gt;sda1&lt;/em&gt; to &lt;em&gt;ext4&lt;/em&gt;? Yes.&lt;/li&gt;
  &lt;li&gt;Do you want to install boot loader GRUB? Yes.&lt;/li&gt;
  &lt;li&gt;Do you want to install &lt;em&gt;/system&lt;/em&gt; directory as read-write? Yes.&lt;/li&gt;
  &lt;li&gt;Run Android-x86.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you choose GPT at 3rd step, then install EFI and GRUB2 instead of GRUB.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First boot takes several minutes to initialize system preparation.&lt;/p&gt;

&lt;h1 id=&quot;arch-linux-x86_64-vm&quot;&gt;Arch Linux x86_64 VM&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage list ostypes &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ArchLinux_64&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage createvm &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; archlinux_64 &lt;span class=&quot;nt&quot;&gt;--ostype&lt;/span&gt; ArchLinux_64 &lt;span class=&quot;nt&quot;&gt;--register&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--basefolder&lt;/span&gt; /media/Misc/VirtualBox/Machines
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage modifyvm archlinux_64 &lt;span class=&quot;nt&quot;&gt;--memory&lt;/span&gt; 512 &lt;span class=&quot;nt&quot;&gt;--acpi&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--vrde&lt;/span&gt; on &lt;span class=&quot;nt&quot;&gt;--vrdeproperty&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TCP/Ports=5001,5010-5012&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--vrdeproperty&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;TCP/Address=127.0.0.1&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--clipboard&lt;/span&gt; bidirectional
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage createmedium &lt;span class=&quot;nt&quot;&gt;--filename&lt;/span&gt; /media/Misc/VirtualBox/Machines/archlinux_64/archlinux_64.vdi &lt;span class=&quot;nt&quot;&gt;--size&lt;/span&gt; 4000
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage modifymedium /media/Misc/VirtualBox/Machines/archlinux_64/archlinux_64.vdi &lt;span class=&quot;nt&quot;&gt;--resize&lt;/span&gt; 5000
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storagectl archlinux_64 &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; sata &lt;span class=&quot;nt&quot;&gt;--controller&lt;/span&gt; IntelAHCI &lt;span class=&quot;nt&quot;&gt;--portcount&lt;/span&gt; 3
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach archlinux_64 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; hdd &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; /media/Misc/VirtualBox/Machines/archlinux_64/archlinux_64.vdi
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach archlinux_64 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; dvddrive &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; ~/Downloads/archlinux-2017.11.01-x86_64.iso
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage sharedfolder add archlinux_64 &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; WLshare &lt;span class=&quot;nt&quot;&gt;--hostpath&lt;/span&gt; /media/Misc/WLshare
&lt;span class=&quot;c&quot;&gt;# starvm&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage startvm archlinux_64 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; headless
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The VDI file is &lt;a href=&quot;https://forums.virtualbox.org/viewtopic.php?f=35&amp;amp;t=50661&quot;&gt;resized&lt;/a&gt; after creation.&lt;/p&gt;

    &lt;p&gt;Then follow the &lt;a href=&quot;https://www.zhstar.win/2017/11/28/archlinux/&quot;&gt;Arch Linux post&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;VBoxGuestAdditions in Linux guest requires extra effors. Details refer to Arch Linux post.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;virtualbox-guestadditions&quot;&gt;VirtualBox GuestAdditions&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.virtualbox.org/manual/ch04.html#idm2096&quot;&gt;VirtualBox GuestAdditions&lt;/a&gt; consists of device drivers and system applications that optimize the guest operating system for better performance and usability.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Some Linux guest OSes (i.e. Gentoo, Arch Linux) already come with all or part of the VirtualBox GuestAdditions.&lt;/p&gt;

    &lt;p&gt;Just install the corresponding package. For example:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# emerge &lt;span class=&quot;nt&quot;&gt;-avt&lt;/span&gt; app-emulation/virtualbox-guest-additions &lt;span class=&quot;c&quot;&gt;# Gentoo&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; virtualbox-guest-utils/virtualbox-guest-utils-nox &lt;span class=&quot;c&quot;&gt;# archlinux&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This method is always preferred!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Alternatively, we can mount the ISO of GuestAdditions and invoke the relevant installation script manually.&lt;/p&gt;

    &lt;p&gt;Firstly, make sure development tools like &lt;em&gt;gcc&lt;/em&gt;, &lt;em&gt;make&lt;/em&gt;, &lt;em&gt;kernel-headers&lt;/em&gt;, &lt;em&gt;kernel-devel&lt;/em&gt; etc. are present on guest OS. Also confirm the guest OS kernel version matches that of package &lt;em&gt;kernel-headers&lt;/em&gt; and package &lt;em&gt;kernel-devel&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Then, we can obtain the ISO from host by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vboxmanage storageattach&lt;/code&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# lsblk &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;We can also get ISO file from guest OS (Arch Linux) package repository:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; virtualbox-guest-iso
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; /usr/lib/virtualbox/additions/VBoxGuestAdditions.iso
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Another method, is to download the ISO from VirtualBox official website. Whatever methods you choose to get the ISO, make sure it has the same version as VirtualBox VMM on host OS.&lt;/p&gt;

    &lt;p&gt;Once the ISO is obtained, we mount the ISO:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# ll /dev/cdrom
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# &lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; /mnt/vbox
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# mount &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; loop /dev/cdrom /mnt/vbox
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# ll /mnt/vbox
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Lastly, install GuestAdditions:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# sh /mnt/vbox/VBoxLinuxAdditions.run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Restart guest OS before VirtualBox guest additions take effect.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A real pactice on Arch guest&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Gentoo host: kernel-4.12.5, VirtualBox 5.1.26.&lt;/li&gt;
      &lt;li&gt;Arch guest: kernel-4.13.12,  VirtualBox 5.2.2.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Gentoo is relatively conservative on package rolling update compared to Arch Linux. So installing GuestAdditions directly from Arch repository is beffer.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; virtualbox-guest-utils &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;X Window&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# or&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# pacman &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; virtualbox-guest-utils-nox &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;no X&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Enable &lt;em&gt;vboxservice&lt;/em&gt; unit service to load &lt;em&gt;vboxguest&lt;/em&gt;, &lt;em&gt;vboxsf&lt;/em&gt;, and &lt;em&gt;vboxvideo&lt;/em&gt; kernel modules.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# systemctl &lt;span class=&quot;nb&quot;&gt;enable &lt;/span&gt;vboxservice
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;VBoxClient (or the &lt;em&gt;VBoxClient-all&lt;/em&gt; wrapper) is another unit service from the GuestAdditions. It manages clipboard, seamless window display, etc. The associated &lt;em&gt;/etc/xdg/autostart/vboxclient.desktop&lt;/em&gt; launches VBoxClient-all on logon. VBoxClient-all script launches VBoxClient as:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;user@host ~]&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxClient &lt;span class=&quot;nt&quot;&gt;--clipboard&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--draganddrop&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--seamless&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--display&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--checkhostversion&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Check Autostart section above on how to launch VBoxclient alongside with awesome.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;virtualbox-sharedfolder&quot;&gt;VirtualBox sharedfolder&lt;/h2&gt;

&lt;p&gt;Make sure &lt;em&gt;vboxservice&lt;/em&gt; is enabled and started.&lt;/p&gt;

&lt;p&gt;Add shared folder:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@host ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage sharedfolder add archlinux &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; share_name &lt;span class=&quot;nt&quot;&gt;--hostpath&lt;/span&gt; /path/to/host/folder &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--automount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Arch Linux guest can mount the shared folder manually (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mount -t vboxsf&lt;/code&gt;), automatically (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vboxmanage --automount&lt;/code&gt;), or by &lt;em&gt;fstab&lt;/em&gt;. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--automount&lt;/code&gt; provided, then by default, the folder is mounted for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root:vboxsf&lt;/code&gt;. For other accounts to read and write, do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usermod -aG vboxsf &amp;lt;username&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Alternatively, use &lt;em&gt;fstab&lt;/em&gt; to flexibly control mount options:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/fstab

wlshare        /media/wlshare        vboxsf        nodev,nosuid,noexec,uid=root,gid=vboxsf,rw,iocharset=utf8,dmode=0770,fmode=0660        0 0

wlshare        /media/wlshare        vboxsf        nodev,nosuid,noexec,noauto,uid=root,gid=vboxsf,rw,iocharset=utf8,dmode=0770,fmode=0660,x-systemd.automount        0 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;em&gt;noauto&lt;/em&gt; option is to avoid service racing on booting. For example, GuestAdditions are not loaded yet while &lt;em&gt;fstab&lt;/em&gt; tries to mount it.&lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;x-systemd.automount&lt;/em&gt; will create &lt;em&gt;media-wlshare&lt;/em&gt; unit upon &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl daemon-reload&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Only &lt;em&gt;root&lt;/em&gt; is allowed to mount &lt;em&gt;vboxsf&lt;/em&gt; device. So the &lt;em&gt;user&lt;/em&gt; option is not permissible.&lt;/li&gt;
  &lt;li&gt;Read &lt;a href=&quot;https://unix.stackexchange.com/a/188604&quot;&gt;Why nodev,nosuid,noexe are important?&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;expand-vdi-size&quot;&gt;Expand VDI Size&lt;/h2&gt;

&lt;p&gt;Occasionally, the guest OS warns running out of disk space when you should &lt;a href=&quot;https://forums.virtualbox.org/viewtopic.php?f=35&amp;amp;t=50661&quot;&gt;resize&lt;/a&gt; the VM disk and parition thereof.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Firstly, make sure the guest does &lt;strong&gt;not&lt;/strong&gt; have snapshots. If there exist any, delete all of them.&lt;/li&gt;
  &lt;li&gt;Resizing does not work if the guest VM resides on fix-sized VDI.&lt;/li&gt;
  &lt;li&gt;Currently, only expansion is supported. You cannot decrease any VDI or partitions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here, I will show an example of expanding &lt;em&gt;archlinux_64&lt;/em&gt; VM above. On the host:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage list hdds
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage modifymedium /media/Misc/VirtualBox/Machines/archlinux_64/archlinux_64.vdi &lt;span class=&quot;nt&quot;&gt;--resize&lt;/span&gt; 10000
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage list hdds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The VDI is increasing from 5GiB to 10GiB. Next, we should let the VM known the expansion. Basically, we attach to the VM a live booting media containing &lt;em&gt;parted&lt;/em&gt; or &lt;em&gt;gparted&lt;/em&gt; tool. GParted live CD and Arch Linux ISO are such examples. On the host:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage showvminfo archlinux_64
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage storageattach archlinux_64 &lt;span class=&quot;nt&quot;&gt;--storagectl&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;SATA Controller&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;--device&lt;/span&gt; 0 &lt;span class=&quot;nt&quot;&gt;--type&lt;/span&gt; dvddrive &lt;span class=&quot;nt&quot;&gt;--medium&lt;/span&gt; ~/Downloads/archlinux-2018.01.01-x86_64.iso
user@tux ~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;VBoxManage showvminfo archlinux_64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please make sure boot the VM on the attached ISO instead of VDI. In the live system, suppose &lt;em&gt;/dev/sda&lt;/em&gt; represents VDI:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] fdisk/blkid/lsblk/findmnt&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@archiso / &lt;span class=&quot;c&quot;&gt;#] parted -a optimal /dev/sda&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; print free
The backup GPT table is not at the end of the disk, as it should be. This might mean that another operating system believes the disk is smaller. Fix, by moving the backup to the end &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;and removing the old backup&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;? Fix/Ignore/Cancel?
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; Fix
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; print free
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; resizepart 1 100%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;parted&lt;/em&gt; detects the VDI expanded and reminds &lt;em&gt;Fix&lt;/em&gt;. The key is &lt;em&gt;resizepart&lt;/em&gt; (or &lt;em&gt;resize&lt;/em&gt; depending on &lt;em&gt;parted&lt;/em&gt; version) epxanding (100%) the &lt;em&gt;root&lt;/em&gt; partition to include newly added space. That&apos;s all!&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Some posts write &lt;em&gt;resizepart&lt;/em&gt; can be done on guest OS directly as long as swap partition/file is turned off.&lt;/li&gt;
  &lt;li&gt;For Windows guest, use enclosed &lt;em&gt;disk management&lt;/em&gt; to finish the job.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;centos-82-amd64&quot;&gt;CentOS 8.2 Amd64&lt;/h1&gt;

&lt;p&gt;This section describes procedures to manage CentOS 8.2 VM:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Start the VM.&lt;/p&gt;

    &lt;p&gt;Enable the Host-only interface &lt;em&gt;/etc/sysconfig/network-scripts/ifcfg-enp0s8&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Start the VM in headless mode either on command line or by GUI.&lt;/p&gt;

    &lt;p&gt;SSH into the VM.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Configure repository mirror.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnf group install &apos;Development Tools&apos;&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Insert GuestAdditions CD; mount &lt;em&gt;sr0&lt;/em&gt;; install GuestAdditions.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Add shared folder.&lt;/li&gt;
      &lt;li&gt;Add clipboard.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/VirtualBox&quot;&gt;gentoo wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://baige5117.github.io/blog/install_virtualbox_in_gentoo.html&quot;&gt;install_virtualbox_in_gentoo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/rustymyers/scripts/blob/master/shell/createVBoxVM.sh&quot;&gt;createVBoxVM.sh&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://serverfault.com/questions/171665/how-to-attach-a-virtual-hard-disk-using-vboxmanage&quot;&gt;how-to-attach-a-virtual-hard-disk-using-vboxmanage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.virtualbox.org/manual/ch07.html#idp46785385220400&quot;&gt;Remote virtual machines&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.howtoforge.com/vboxheadless-running-virtual-machines-with-virtualbox-4.3-on-a-headless-ubuntu-14.04-lts-server&quot;&gt;headless vm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://forums.virtualbox.org/viewtopic.php?f=7&amp;amp;t=18012&quot;&gt;guestadditions in headless&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://askaralikhan.blogspot.com/2011/01/virtualbox-40-creating-virtual-machine.html&quot;&gt;vbox create headless vm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.virtualbox.org/manual/ch07.html#idm3213&quot;&gt;VBoxManage createvm manully&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Gentoo rootfs over LVM encrypted in LUKS container.</title>
   <link href="/2015/08/15/gentoo-over-lvm-luks/"/>
   <updated>2015-08-15T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/08/15/gentoo-over-lvm-luks</id>
   <content type="html">&lt;h1 id=&quot;system-scheme&quot;&gt;System scheme&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&apos;&lt;em&gt;/boot&lt;/em&gt;&apos; partition resides on USB stick, say &lt;em&gt;sdc1&lt;/em&gt; partition.&lt;/li&gt;
  &lt;li&gt;&apos;&lt;em&gt;/boot/efi&lt;/em&gt;&apos; is shared among Windows and Gentoo.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;rootfs&lt;/em&gt; (&apos;&lt;em&gt;/, swap, /home&lt;/em&gt;&apos;) mountpoints were created op top of LVM group, say &lt;em&gt;vg1&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;vg1&lt;/em&gt; LVM group lays over &lt;em&gt;Dm-Crypt, LUKS&lt;/em&gt; encrypted sda8*.&lt;/li&gt;
  &lt;li&gt;Use &lt;em&gt;keyfile&lt;/em&gt; to encrypt &lt;em&gt;rootfs&lt;/em&gt;. &lt;em&gt;keyfile&lt;/em&gt; isteself was encrypted by &lt;em&gt;GnuPG&lt;/em&gt; and placed at USB stick, say &lt;em&gt;sdc1&lt;/em&gt; (same as &lt;em&gt;/boot&lt;/em&gt;).&lt;/li&gt;
  &lt;li&gt;The installation process depends mainly on Gentoo LiveCD.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;prepare-partitions&quot;&gt;Prepare partitions&lt;/h1&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parted -a optimal /dev/sda&lt;/code&gt; to get a disk partition for &lt;em&gt;rootfs&lt;/em&gt;. I will use &lt;em&gt;rootfs&lt;/em&gt; for &apos;&lt;em&gt;/, swap, /home&lt;/em&gt;&apos; mountpoints in this post.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Run the very first command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit s&lt;/code&gt; in &lt;em&gt;parted&lt;/em&gt; to display disk partitions as &lt;em&gt;sector&lt;/em&gt;. When creating partition with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt; unit, it will be well aligned.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For &lt;em&gt;parted&lt;/em&gt; example, refer to &lt;a href=&quot;http://www.fangxiang.tk/2015/03/25/gentoo-installation/&quot;&gt;gentoo installation&lt;/a&gt; and &lt;a href=&quot;http://www.fangxiang.tk/2015/07/23/kali-usb-persistence/&quot;&gt;kali usb persistence&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Say &apos;&lt;em&gt;/dev/sda8&lt;/em&gt;&apos; is created for &lt;em&gt;rootfs&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parted -a optimal /dev/sdc&lt;/code&gt; to create &apos;&lt;em&gt;/boot&lt;/em&gt;&apos; partition on USB stick &apos;&lt;em&gt;/dev/sdc1&lt;/em&gt;&apos;.&lt;/p&gt;

&lt;p&gt;&apos;&lt;em&gt;/boot&lt;/em&gt;&apos; is &lt;em&gt;NOT&lt;/em&gt; encrypted! You can use the whole USB space to hold &apos;&lt;em&gt;/boot&lt;/em&gt;&apos;, or just spare around 256MB parition.&lt;/p&gt;

&lt;p&gt;Then formate the partition as &lt;em&gt;ext2&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkfs.ext2 -L &apos;usb boot&apos; /dev/sdc1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;cryptsetup-keyfile&quot;&gt;cryptsetup keyfile&lt;/h1&gt;

&lt;h2 id=&quot;dm-crypt-and-luks&quot;&gt;dm-crypt and LUKS&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;dm-crypt&lt;/strong&gt; is a disk encryption system using the kernels &lt;em&gt;crypto API&lt;/em&gt; framework and &lt;em&gt;device mapper&lt;/em&gt; subsystem.&lt;/p&gt;

&lt;p&gt;With &lt;em&gt;dm-crypt&lt;/em&gt;, administrators can encrypt entire disks, logical volumes, partitions, but also single files.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;dm-crypt&lt;/em&gt; subsystem supports the &lt;em&gt;Linux Unified Key Setup&lt;/em&gt; (LUKS) structure, which allows for multiple keys to access the encrypted data, as well as manipulate the keys (such as changing the keys, adding additional passphrases, etc.)&lt;/p&gt;

&lt;p&gt;Although &lt;em&gt;dm-crypt&lt;/em&gt; supports &lt;em&gt;non&lt;/em&gt;-LUKS setups as well, this article will focus on the LUKS functionality mostly due to its flexibility, manageability as well as broad support in the community.&lt;/p&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/Dm-crypt&quot;&gt;Dm-crypt&lt;/a&gt; and &lt;a href=&quot;https://wiki.gentoo.org/wiki/DM-Crypt_LUKS&quot;&gt;Dm-Crypt LUKS&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;keyfile&quot;&gt;Keyfile&lt;/h2&gt;

&lt;p&gt;We use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cryptsetup&lt;/code&gt; command from LiveCD to encrypt &lt;em&gt;rootfs&lt;/em&gt; partition &apos;&lt;em&gt;/dev/sda8&lt;/em&gt;&apos;. We can use &lt;strong&gt;passphrase&lt;/strong&gt; or &lt;strong&gt;keyfile&lt;/strong&gt; as encryption key.&lt;/p&gt;

&lt;p&gt;Considering the length, randomness and complexity of encryption requirements a &lt;em&gt;keyfile&lt;/em&gt; seems to be the right spot.&lt;/p&gt;

&lt;p&gt;We first generate a ramdom &lt;em&gt;keyfile&lt;/em&gt; for &lt;em&gt;rootfs&lt;/em&gt; encryption. This &lt;em&gt;keyfile&lt;/em&gt; is usually put at a secure place, i.e. USB stick.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In this scheme, &lt;em&gt;keyfile&lt;/em&gt; and &apos;&lt;em&gt;/boot&lt;/em&gt;&apos; share the same USB stick partition.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If attacker gets the USB stick, system is decrypted!! So next, we need to encrypt this &lt;em&gt;keyfile&lt;/em&gt; by &lt;strong&gt;GnuPG&lt;/strong&gt; before storing it on USB stick.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkdir /mnt/sdc1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount /dev/sdc1 /mnt/sdc1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkdir /dev/sdc1/key&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dd &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/urandom &lt;span class=&quot;nv&quot;&gt;bs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;8388607 &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 | gpg &lt;span class=&quot;nt&quot;&gt;--symmetric&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cipher-algo&lt;/span&gt; AES256 &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; ~/Desktop/luks-key.gpg
&lt;span class=&quot;c&quot;&gt;# cp /path/to/luks-key.gpg /mnt/sdc1/key/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/Sakaki%27s_EFI_Install_Guide/Preparing_the_LUKS-LVM_Filesystem_and_Boot_USB_Key#Creating_a_Password-Protected_Keyfile_for_LUKS&quot;&gt;Preparing the LUKS-LVM Filesystem and Boot USB Key&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You will be asked for passphrase to encrypt &lt;em&gt;keyfile&lt;/em&gt;. Don&apos;t forget passphrase!&lt;/p&gt;

&lt;p&gt;If you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpg&lt;/code&gt; in LiveCD &lt;em&gt;root&lt;/em&gt; shell, you might get the following error even though you set &apos;export GPG_TTY=$(tty)&apos; as the reference mentioned:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gpg: directory `/root/.gnupg&apos; created
gpg: new configuration file `/root/.gnupg/gpg.conf&apos; created
gpg: WARNING: options in `/root/.gnupg/gpg.conf&apos; are not yet active during this run
gpg: keyring `/root/.gnupg/pubring.gpg&apos; created
No protocol specified

(pinentry:10992): Gtk-WARNING **: cannot open display: :0
gpg-agent[10991]: can&apos;t connect to the PIN entry module: End of file
gpg-agent[10991]: command get_passphrase failed: No pinentry
gpg: problem with the agent: No pinentry
gpg: error creating passphrase: Operation cancelled
gpg: symmetric encryption of `[stdin]&apos; failed: Operation cancelled
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Refer to &lt;a href=&quot;https://forums.gentoo.org/viewtopic-p-7485020.html&quot;&gt;Genkernel initramfs with LUKS+GPG key&lt;/a&gt; and &lt;a href=&quot;https://bbs.archlinux.org/viewtopic.php?id=120181&quot;&gt;Using gpg in mkinitcpio hook, gpg doesn&apos;t ask for a password&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This might be related to &lt;em&gt;&amp;gt;app-crypt/gnupg-2.0&lt;/em&gt; version and &lt;em&gt;pinentry&lt;/em&gt; support. To get this issue solved:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Generate &lt;em&gt;keyfile&lt;/em&gt; in another workable environment.&lt;/li&gt;
  &lt;li&gt;Switch to normal user account shell when run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpg&lt;/code&gt; command and get he decrypted temporary &lt;em&gt;luks-key&lt;/em&gt; file for LiveCD.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;format-rootfs-using-luks&quot;&gt;Format &lt;em&gt;rootfs&lt;/em&gt; using LUKS&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--decrypt&lt;/span&gt; /mnt/sdc1/key/luks-key.gpg &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ~/Desktop/luks-key
&lt;span class=&quot;c&quot;&gt;# cryptsetup --cipher serpent-xts-plain64 --key-size 512 --hash sha512 --key-file /path/to/luks-key luksFormat /dev/sda8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pay attention to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cipher serpent-xts-plain64 --key-size 512 --hash sha512&lt;/code&gt; which reminds us the related kernel option must be &apos;Y&apos; &lt;strong&gt;NOT&lt;/strong&gt; &apos;M&apos;.&lt;/p&gt;

&lt;p&gt;Check the formating effect:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cryptsetup luksDump /dev/sda8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;adding-a-fallback-passphrase-optional-step&quot;&gt;Adding a Fallback Passphrase (Optional Step)&lt;/h2&gt;

&lt;p&gt;If we lost the &lt;em&gt;gpg&lt;/em&gt; passphrase or the &lt;em&gt;keyfile&lt;/em&gt;, we lost the entire system data. Besides the &lt;em&gt;keyfile&lt;/em&gt;, we add a fallback passphrase.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cryptsetup --key-file /path/to/luks-key luksAddKey /dev/sda8&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cryptsetup luksDump /dev/sda8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;creating-the-lvm-structure-on-top-of-luks&quot;&gt;Creating the LVM Structure on Top of LUKS&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cryptsetup --key-file /path/to/luks-key luksOpen /dev/sda8 gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ls /dev/mapper&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# pvcreate /dev/mapper/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vgcreate vg1 /dev/mapper/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lvcreate --size 4G --name swap vg1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lvcreate --size 18G --name root vg1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lvcreate --extents 100%FREE --name home vg1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# pvdisplay&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vgdisplay&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lvdisplay&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vgchange --available y&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lvscan&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ls /dev/mapper&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;formatting-and-mounting-the-lvm-logical-volumes-lvs&quot;&gt;Formatting and Mounting the LVM Logical Volumes (LVs)&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkswap -L &quot;swap&quot; /dev/mapper/vg1-swap&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkfs.ext4 -L &quot;root&quot; /dev/mapper/vg1-root&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkfs.ext4 -m 0 -L &quot;home&quot; /dev/mapper/vg1-home&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# swapon -v /dev/mapper/vg1-swap&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t ext4 /dev/mapper/vg1-root /mnt/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkdir -v /mnt/gentoo/{home,boot}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t ext4 /dev/mapper/vg1-home /mnt/gentoo/home&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# umount -v /dev/sdc1&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t ext2 /dev/sdc1 /mnt/gentoo/boot&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkdir /mnt/gentoo/boot/efi&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v /dev/sda2 /mnt/gentoo/boot/efi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;chroot-for-installing&quot;&gt;Chroot for installing&lt;/h1&gt;

&lt;p&gt;Final preparation:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mirrorselect -i -o &amp;gt;&amp;gt; /mnt/gentoo/etc/portage/make.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkdir -p -v /mnt/gentoo/etc/portage/repos.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cp -v /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# nano -w /mnt/gentoo/etc/portage/repos.conf/gentoo.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make &lt;em&gt;gentoo.conf&lt;/em&gt; contents as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[DEFAULT]
main-repo = gentoo

[gentoo]
location = /usr/portage
sync-type = rsync
sync-uri = rsync://rsync.cn.gentoo.org/gentoo-portage
auto-sync = yes

# for daily squashfs snapshots
#sync-type = squashdelta
#sync-uri = mirror://gentoo/../snapshots/squashfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The old portage sync system use &lt;em&gt;SYNC=rsync://rsync.cn.gentoo.org/gentoo-portage&lt;/em&gt; in &lt;em&gt;make.conf&lt;/em&gt;. In new &amp;gt;portage-2.2.16, it is &lt;em&gt;sync-url&lt;/em&gt; in &lt;em&gt;gentoo.conf&lt;/em&gt;. To get the &lt;em&gt;sync-url&lt;/em&gt; value:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mirrorselect -i -r -o | sed &apos;s/^SYNC=/sync-uri = /;s/&quot;//g&apos; &amp;gt;&amp;gt; /mnt/gentoo/etc/portage/repos.conf/gentoo.conf &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally &lt;em&gt;chroot&lt;/em&gt; into new environment:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cp -v -L /etc/resolv.conf /mnt/gentoo/etc/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# chroot /mnt/gentoo /bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# source /etc/profile &amp;amp;&amp;amp; export PS1=&quot;(chroot) $PS1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;s&gt; After entering *chroot* environment, the very first is to mask GnuPG 2.0. Refer to *Tips -&amp;gt; GnuPG* at the end of post. &lt;/s&gt;

&lt;h2 id=&quot;return-to-chroot-environment&quot;&gt;Return to &lt;em&gt;chroot&lt;/em&gt; environment&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cryptsetup --key-file=/path/to/luks-key luksOpen /dev/sda8 gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vgchange --available y&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# lvscan&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ls /dev/mapper/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# swapon -v /dev/mapper/vg1-swap&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t ext4 /dev/mapper/vg1-root /mnt/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t ext4 /dev/mapper/vg1-home /mnt/gentoo/home&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t ext2 UUID=63053222-d5f9-43af-a7ce-76f0ca5a14ed /mnt/gentoo/boot&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v /dev/sda2 /mnt/gentoo/boot/efi&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cp -v -L /etc/resolv.conf /mnt/gentoo/etc/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v -t proc proc /mnt/gentoo/proc&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v --rbind /sys /mnt/gentoo/sys&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v --rbind /dev /mnt/gentoo/dev&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v --make-rslave /mnt/gentoo/sys&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -v --make-rslave /mnt/gentoo/dev&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# chroot /mnt/gentoo /bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# source /etc/profile &amp;amp;&amp;amp; export PS1=&quot;(chroot) $PS1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;initramfs-and-grub2&quot;&gt;&lt;em&gt;initramfs&lt;/em&gt; and &lt;em&gt;grub2&lt;/em&gt;&lt;/h1&gt;

&lt;p&gt;After getting into &lt;em&gt;chroot&lt;/em&gt; environment, the most procedures, pleae refer to &lt;a href=&quot;http://www.fangxiang.tk/2015/03/25/gentoo-installation/&quot;&gt;gentoo installation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The main difference from that link, is &lt;em&gt;genkernel&lt;/em&gt; and &lt;em&gt;grub2&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;kernel-option-support&quot;&gt;Kernel option support&lt;/h2&gt;

&lt;p&gt;From the above, we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--cipher serpent-xts-plain64&lt;/code&gt; and ` –hash sha512` which reminds us the related kernel option must be &lt;strong&gt;Y&lt;/strong&gt; instead of &apos;M&apos;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;CRYPTO_SERPENT Y&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;CRYPTO_SHA512 Y&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why they are should be &apos;Y&apos; instead of &apos;M&apos;? The boot process is basically:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Power on;&lt;/li&gt;
  &lt;li&gt;EFI firmware find the default bootloader Gentoo &lt;em&gt;grub2&lt;/em&gt; at &apos;&lt;em&gt;/dev/sda2/EFI/gentoo/grub64.efi&lt;/em&gt;&apos;;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;grub2&lt;/em&gt; launch &lt;em&gt;initramfs&lt;/em&gt; into RAM;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;initramfs&lt;/em&gt; found &lt;em&gt;GnuPG keyfile&lt;/em&gt; at &apos;&lt;em&gt;/boot/key&lt;/em&gt;&apos; and ask user for decryption; decrypted &lt;em&gt;keyfile&lt;/em&gt; is used to decrypt &lt;em&gt;rootfs&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Control pass to &lt;em&gt;init&lt;/em&gt; scripts. After that, kernel modules loaded.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You find that if the two kernel options compiled as modules &apos;M&apos;, then you cannot pass the 4th step. No &lt;em&gt;serpent&lt;/em&gt; and &lt;em&gt;sha512&lt;/em&gt; function for &lt;em&gt;keyfile&lt;/em&gt; decryption. This is the error message at boot:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;http://pastebin.com/fZgMwyNw&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;sys-kernel/genkernel cryptsetup&quot; &amp;gt; /etc/portage/package.use/genkernel&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -av genkernel&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# genkernel --lvm --luks --gpg --busybox --install initramfs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You see &lt;em&gt;genkernel&lt;/em&gt; takes &lt;em&gt;lvm&lt;/em&gt;, &lt;em&gt;luks&lt;/em&gt;, &lt;em&gt;gpg&lt;/em&gt;, and &lt;em&gt;busybox&lt;/em&gt; parameter. Don&apos;t worry about the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpg&lt;/code&gt; version issue mentioned earlier! &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man genkernel&lt;/code&gt; shows it includes &lt;em&gt;GnuPG 1.x&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;--[no-]gpg
           Includes or excludes support for GnuPG 1.x, the portable standalone
           branch of GnuPG. A key can be made from gpg --symmetric -o
           /path/to/LUKS-key.gpg /path/to/LUKS-key . After that, re-point the
           root_key argument to the new .gpg file.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Some posts mention &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emerge -av app-crypt/gnupg lvm2 busybox cryptsetup&lt;/code&gt; in the &lt;em&gt;chroot&lt;/em&gt; system before &lt;em&gt;genkernel&lt;/em&gt;. Basically, these tools are only needed in LiveCD and &apos;genkernel&apos;. In our new Gentoo system, it is not a must.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;sys-kernel/genkernel cryptsetup&lt;/em&gt; USE flag will draw in &lt;em&gt;cryptsetup&lt;/em&gt;, and then &lt;em&gt;lvm2&lt;/em&gt; in &lt;em&gt;chroot&lt;/em&gt;, while &lt;em&gt;busybox&lt;/em&gt; is an essential &lt;em&gt;@system&lt;/em&gt; package which is included in &lt;em&gt;stage3&lt;/em&gt; tar bar. You can run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;equery u busybox&lt;/code&gt;, and find &lt;em&gt;static&lt;/em&gt; USE flag. Try:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -pvc cryptsetup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It will reminds:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Calculating dependencies... done!
  sys-fs/cryptsetup-1.6.5 pulled in by:
    sys-kernel/genkernel-3.4.49.2 requires sys-fs/cryptsetup

&amp;gt;&amp;gt;&amp;gt; No packages selected for removal by depclean
Packages installed:   549
Packages in world:    38
Packages in system:   44
Required packages:    549
Number to remove:     0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There is no need to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc-update add lvm boot&lt;/code&gt;, for this is only useful when there is any other LVM devices like external removable LVM disks, USB stick etc.&lt;/p&gt;

&lt;h2 id=&quot;grub2&quot;&gt;Grub2&lt;/h2&gt;

&lt;p&gt;The core is to set the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB_CMDLINE_LINUX&lt;/code&gt; parameters for &lt;em&gt;kernel&lt;/em&gt; and &lt;em&gt;init&lt;/em&gt; scripts. Some of those parameters are indeed consumed by the kernel (a reasonable complete list of which is provided by kernel.org); however, others are realy targeted at the &lt;em&gt;init&lt;/em&gt; script. The Linux kernel passes the &lt;em&gt;init&lt;/em&gt; script (or program) any parameters it has not already rocessed as arguments, and the &lt;em&gt;init&lt;/em&gt; script can also read the full command line in any event, via /proc/cmdline.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# nano -w /etc/default/grub
GRUB_CMDLINE_LINUX=&quot;crypt_root=UUID=8e105495-5a45-4297-b6ad-6e2d97abb461 dolvm root=/dev/mapper/vg1-root rootfstype=ext4 root_keydev=UUID=63053222-d5f9-43af-a7ce-76f0ca5a14ed root_key=key/luks-key.gpg&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;crypt_root: this tells &lt;em&gt;init&lt;/em&gt; (provided by &lt;em&gt;genkernel&lt;/em&gt;) script which partition it should attempt to decrypt with &lt;em&gt;cryptsetup&lt;/em&gt;. It is set to UUID of the LUKS formatted partition, say &lt;em&gt;sda8&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;dolvm: activate LVM volumes on bootup.&lt;/li&gt;
  &lt;li&gt;rootfstype: root file system type.&lt;/li&gt;
  &lt;li&gt;root: the location of the root filesystem to the kernel.&lt;/li&gt;
  &lt;li&gt;root_keydev: if necessary provide the name of the device that carries the root_key. If unset while using root_key, it will automatically look for the device in every boot. It specifies the device path of device on which the &lt;em&gt;keyfile&lt;/em&gt; is located. In this scheme, it is the &apos;&lt;em&gt;/boot&lt;/em&gt;&apos; USB stick.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;root_key: In case your root is encrypted with a key, you can use a device like a usb pen to store the key. This value should be the key path relative to the mount point. In this scheme, it is in the sub-directory &lt;em&gt;key/luks-key.gpg&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;If it has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gpg&lt;/code&gt; extension (as our case), the &lt;em&gt;init&lt;/em&gt; script will treat it as being a &lt;em&gt;gpg&lt;/em&gt; encrypted &lt;em&gt;keyfile&lt;/em&gt;, and prompt for a passphrase to unlock the &lt;em&gt;keyfile&lt;/em&gt; first (either textually at the console, or using the splash screen manager if the system sets that).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Here we use UUID instead of device file path &apos;&lt;em&gt;/dev/sda8&lt;/em&gt;&apos; or &apos;&lt;em&gt;/dev/sdc1&lt;/em&gt;&apos;. Since UUID is unique while device path name might change. For example, if current PC is plugged in 3 usb sticks as &apos;&lt;em&gt;/dev{/sdb,/sdc,/sdd}&lt;/em&gt;&apos; and none of them is the boot stick, &lt;em&gt;initramfs&lt;/em&gt; even cannot find the &lt;em&gt;gpg keyfile&lt;/em&gt; location.&lt;/li&gt;
  &lt;li&gt;More about these command please read &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man genkernel&lt;/code&gt; and &lt;em&gt;kernel.org&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# grub2-mkconfig -o /boot/grub/grub.cfg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;em&gt;chroot&lt;/em&gt; environment, &lt;em&gt;grub2-mkconfig&lt;/em&gt; and  &lt;em&gt;os-prober&lt;/em&gt; might fail to generate Windows menu. Don&apos;t worry! You can use the following template to edit &apos;&lt;em&gt;/etc/grub.d/40_custom&lt;/em&gt;&apos;. Or run &lt;em&gt;grub2-mkconfig&lt;/em&gt; again when log into the real new system.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;menuentry &lt;span class=&quot;s1&quot;&gt;&apos;Windows Boot Manager (on /dev/sda2)&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--class&lt;/span&gt; windows &lt;span class=&quot;nt&quot;&gt;--class&lt;/span&gt; os &lt;span class=&quot;nv&quot;&gt;$menuentry_id_option&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;osprober-efi-DAD1-F557&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        insmod part_gpt
        insmod fat
        &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;hd0,gpt2&apos;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; x&lt;span class=&quot;nv&quot;&gt;$feature_platform_search_hint&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; xy &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
          &lt;/span&gt;search &lt;span class=&quot;nt&quot;&gt;--no-floppy&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--fs-uuid&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;root &lt;span class=&quot;nt&quot;&gt;--hint-bios&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;hd0,gpt2 &lt;span class=&quot;nt&quot;&gt;--hint-efi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;hd0,gpt2 &lt;span class=&quot;nt&quot;&gt;--hint-baremetal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ahci0,gpt2  DAD1-F557
        &lt;span class=&quot;k&quot;&gt;else
          &lt;/span&gt;search &lt;span class=&quot;nt&quot;&gt;--no-floppy&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--fs-uuid&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;root DAD1-F557
        &lt;span class=&quot;k&quot;&gt;fi
        &lt;/span&gt;chainloader /EFI/Microsoft/Boot/bootmgfw.efi
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;fstab&quot;&gt;fstab&lt;/h1&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# UUID of usb stick
UUID=&quot;aaa-bbb-ccc-ddd...&quot;	/boot	ext2	noauto,noatime	1 2
/dev/sda2	/boot/efi	vfat	noauto,noatime	1 0
/dev/mapper/vg1-root	/	ext4	noatime,errors=remount-ro	0 1
/dev/mapper/vg1-swap	none	swap	sw	0 0
/dev/mapper/vg1-home	/home	ext4	defaults	0 0
/dev/sda1	/mnt/Recovery	ntfs-3g		noauto,ro	0 0
/dev/sda4	/mnt/Win81	ntfs-3g		noauto,ro	0 0
/dev/sda5	/media/Data	ntfs-3g		noauto,nls=utf8,locale=zh_CN.utf8,uid=zachary,gid=users,dmask=022,fmask=133	0 0
/dev/sda6	/media/Misc	ntfs-3g		nls=utf8,locale=zh_CN.utf8,uid=zachary,gid=users,dmask=022,fmask=133	0 0
/dev/sda7	/media/WLshare	ntfs-3g		nls=utf8,locale=zh_CN.utf8,uid=zachary,gid=users,users,dmask=022,fmask=133	0 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;get-out-of-chroot&quot;&gt;Get out of &lt;em&gt;chroot&lt;/em&gt;&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# exit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# swapoff -v /dev/mapper/vg1-swap&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# umount -lv /mnt/gentoo/home&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# umount -lv /mnt/gentoo/boot{/eif,}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# umount -lv /mnt/gentoo/dev{/shm,/pts,}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# umount -lv /mnt/gentoo{/proc,/sys,}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# vgchange --available n&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cryptsetup luksClose gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# reboot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;tips&quot;&gt;Tips&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;mtab&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ln -vsf /proc/self/mounts /etc/mtab&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;XSESSION&lt;/p&gt;

    &lt;p&gt;When emerging &lt;em&gt;xorg&lt;/em&gt; and &lt;em&gt;xfce4&lt;/em&gt;, the wiki recommends setting:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo XSESSION=&quot;Xfce4&quot; &amp;gt; /etc/env.d/90xsession&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;for all users on the system. This is not a good idea since &lt;em&gt;root&lt;/em&gt; account can run X as well, which is NOT a good scheme.&lt;/p&gt;

    &lt;p&gt;So remove &apos;&lt;em&gt;/etc/env.d/90xsession&lt;/em&gt;&apos; if exists.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Editor&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c&quot;&gt;# eselect editor set &quot;/usr/local/bin/ect&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Run &lt;em&gt;eselect&lt;/em&gt; as root set the system default editor for all users. Of course, you can also use method in &lt;a href=&quot;http://www.fangxiang.tk/2014/07/12/emacs-configuration/&quot;&gt;emacs configuration&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;[outdated] GnuPG&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;This is outdated.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Though not necessary to emerge GnuPG in the new system. But later on, package &lt;em&gt;layman&lt;/em&gt; will draw in &lt;em&gt;git&lt;/em&gt; which in turn draws in GnuPG. As mentioned, &lt;em&gt;&amp;gt;app-crypt/gnupg-2.0&quot; will cause *pinentry&lt;/em&gt; issue.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;=app-crypt/gnupg-2*&quot; &amp;gt; /etc/portage/package.mask/gnupg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This should be the 1st thing after entering &lt;em&gt;chroot&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;http://ceyes.github.io/2015-06/Gentoo-Setup-LVM-over-LUKS/&lt;/li&gt;
  &lt;li&gt;https://wiki.gentoo.org/wiki/Sakaki%27s_EFI_Install_Guide/Preparing_the_LUKS-LVM_Filesystem_and_Boot_USB_Key&lt;/li&gt;
  &lt;li&gt;http://www.gentoo-wiki.info/SECURITY_System_Encryption_DM-Crypt_with_LUKS&lt;/li&gt;
  &lt;li&gt;http://blog.marek.sapota.org/article/2012/10/07/installing-gentoo-on-an-encrypted-partition.html&lt;/li&gt;
  &lt;li&gt;http://iswwwup.com/t/c1ced3aa98c4/encryption-luks-storing-keyfile-in-encrypted-usb-drive.html&lt;/li&gt;
  &lt;li&gt;http://www.gossamer-threads.com/lists/gentoo/user/300698&lt;/li&gt;
  &lt;li&gt;http://unix.stackexchange.com/questions/183666/booting-gentoo-on-lvm-inside-luks-with-gpg-encrypted-keyfile&lt;/li&gt;
  &lt;li&gt;https://bbs.archlinux.org/viewtopic.php?id=120181&lt;/li&gt;
  &lt;li&gt;https://forums.gentoo.org/viewtopic-p-7485020.html&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Kali Linux Live USB Persistence</title>
   <link href="/2015/07/23/kali-usb-persistence/"/>
   <updated>2015-07-23T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/07/23/kali-usb-persistence</id>
   <content type="html">&lt;p&gt;This post introduces making a bootable Kali USB stick while making changes persistent.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Download &lt;a href=&quot;https://www.kali.org/downloads/&quot;&gt;Kali&lt;/a&gt;.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;kali-linux-1.1.0a-amd64.iso&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Don&apos;t forget to verify &lt;em&gt;SHA1Sum&lt;/em&gt; befere proceding.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Create a bootable Kali Live USB drive. My current working system is &lt;em&gt;Gentoo&lt;/em&gt;. Refer to &lt;a href=&quot;http://docs.kali.org/downloading/kali-linux-live-usb-install&quot;&gt;Making a Kali Bootable USB Drive&lt;/a&gt;.
    &lt;ol&gt;
      &lt;li&gt;Make sure USB flash at least 8GB. Plug USB into PC.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;# parted -l&lt;/p&gt;

        &lt;p&gt;Find the &lt;strong&gt;correct USB device&lt;/strong&gt; name. In my system it is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sdb&lt;/code&gt;. Though &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd&lt;/code&gt; command is magical, you would lost all the data if you provided the wrong device name to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd&lt;/code&gt;.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;The blocksize parameter can be increased, and while it may speed up the operation of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd&lt;/code&gt; command, it can occasionally produce unbootable USB drives, depending on your system and a lot of different factors. The recommended value, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bs=512k&lt;/code&gt;, is conservative and reliable.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Magic:&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# dd if=/path/to/kali-linux-1.1.0a-amd64.iso of=/dev/sdb bs=512k&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;You don&apos;t need to format Live USB. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd&lt;/code&gt; will handle it.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Image the USB drive can take a good amount of time, over ten minutes or more is not unusual, as the sample output below shows. Be patient!&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;After &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd&lt;/code&gt;, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parted&lt;/code&gt; command to see what happens to your USB flash &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/sdb&lt;/code&gt;:&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# parted -a optimal /dev/sdb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;This is my system output:&lt;/p&gt;

        &lt;p&gt;zhtux ~ # parted -a optimal /dev/sdb                                    &lt;br /&gt;
GNU Parted 3.2
Using /dev/sdb
Welcome to GNU Parted! Type &apos;help&apos; to view a list of commands.
(parted) unit MiB                                                       &lt;br /&gt;
(parted) print free                                                     &lt;br /&gt;
Model: SanDisk Cruzer Edge (scsi)
Disk /dev/sdb: 15267MiB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:&lt;/p&gt;

        &lt;p&gt;Number  Start    End       Size      Type     File system  Flags
    0.02MiB  0.03MiB   0.02MiB            Free Space
 1      0.03MiB  2858MiB   2858MiB   primary               boot, hidden
 2      2858MiB  2921MiB   63.0MiB   primary  fat16
    2921MiB  15267MiB  12346MiB           Free Space&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Several points from the output.
        &lt;ol&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit MiB&lt;/code&gt; instead &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit MB&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MiB&lt;/code&gt; shows you the exact value (at Bytes) at the exact disk position, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MB&lt;/code&gt; might round up and the actual position might be 500KB ahead or 500KB after the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MB&lt;/code&gt; value. Similarly, we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GiB&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TiB&lt;/code&gt;. Read &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parted&lt;/code&gt; manual and &lt;a href=&quot;https://wiki.archlinux.org/index.php/GNU_Parted#Rounding&quot;&gt;arch wiki rounding&lt;/a&gt;.&lt;/li&gt;
          &lt;li&gt;
            &lt;p&gt;You can find dd creates two primary partitions &lt;em&gt;1&lt;/em&gt; (2858MiB, with &lt;em&gt;boot&lt;/em&gt; flag) and &lt;em&gt;2&lt;/em&gt; (63.0 MiB). Why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd&lt;/code&gt; creates two partitions? This is due to &lt;em&gt;kali-linux-1.1.0a-amd64.iso&lt;/em&gt; itself a copy of two partitions.&lt;/p&gt;

            &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# fdisk -l /path/to/kali-linux-1.1.0a-amd64.iso&lt;/span&gt;
or
&lt;span class=&quot;c&quot;&gt;# parted /path/to/kali-linux-1.1.0a-amd64.iso print&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;            &lt;/div&gt;

            &lt;p&gt;This is the ouput of from &lt;em&gt;parted&lt;/em&gt;:&lt;/p&gt;

            &lt;p&gt;zhtux mnt # parted /media/WLShare/kali-linux-1.1.0a-amd64/kali-linux-1.1.0a-amd64.iso print
Model:  (file)
Disk /media/WLShare/kali-linux-1.1.0a-amd64/kali-linux-1.1.0a-amd64.iso: 3063MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:&lt;/p&gt;

            &lt;p&gt;Number  Start   End     Size    Type     File system  Flags
 1      32.8kB  2997MB  2997MB  primary               boot, hidden
 2      2997MB  3063MB  66.1MB  primary  fat16&lt;/p&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dd&lt;/code&gt; is a stupid command only copy bytes by bytes fromm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;of&lt;/code&gt;. We can find there are a lot of free space untouched after partition &lt;em&gt;2&lt;/em&gt;. We can make use of the reamaining free space. My &lt;em&gt;Gentoo&lt;/em&gt; Live USB has only one partion consuming the whole flash storage.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Adding USB Persistence with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS&lt;/code&gt; Encryption, refer to &lt;a href=&quot;http://docs.kali.org/downloading/kali-linux-live-usb-persistence&quot;&gt;Kali persistence USB&lt;/a&gt;.
    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;persistence&lt;/em&gt; means changes to Kali system on Live USB remains accross reboots. Basically just create an extra primary partition on Live USB to store persistent files.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Create and format an additional partition on the USB drive. Continue from step 2.6, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parted&lt;/code&gt; tool to create an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ext3&lt;/code&gt; primary partition from the remaining free space.&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary 2921MiB 100%
Warning: You requested a partition from 2921MiB to 15267MiB &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;sectors 5982208..31266815&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
The closest location we can manage is 2921MiB to 15267MiB &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;sectors 5983104..31266815&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
Is this still acceptable to you?
Yes/No? Yes                                                               
Warning: The resulting partition is not properly aligned &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;best performance.
Ignore/Cancel?
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;The &lt;a href=&quot;http://docs.kali.org/downloading/kali-linux-live-usb-persistence&quot;&gt;Kali Doc&lt;/a&gt; recommends &lt;em&gt;Ignore&lt;/em&gt;. Here I want to try the disk alignment for better performance. Refer to &lt;a href=&quot;https://wiki.archlinux.org/index.php/GNU_Parted#Warnings&quot;&gt;arch wiki warnings&lt;/a&gt;. This alignment means the &lt;em&gt;start&lt;/em&gt; position is not aligned. The &lt;em&gt;end&lt;/em&gt; position &lt;em&gt;100%&lt;/em&gt; or &lt;em&gt;-1s&lt;/em&gt; will align itself automatically.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Enter &lt;em&gt;Ignore&lt;/em&gt; to go ahead anyway, print the partition table in sectors to see where it starts, and remove/recreate the partition with the start sector rounded up to increasing powers of 2 until the warning stops.&lt;/p&gt;

        &lt;p&gt;I have tried  2^8, 2^9, 2^10, 2^11. Finally, &lt;em&gt;2^11&lt;/em&gt; works.&lt;/p&gt;

        &lt;blockquote&gt;
          &lt;p&gt;5983104s % 2048 = 896s; 2048s - 896s = 1152s; 5983104s + 1152s = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5984256s&lt;/code&gt;.&lt;/p&gt;
        &lt;/blockquote&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Warning: The resulting partition is not properly aligned &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;best performance.
Ignore/Cancel? Ignore                                                     
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; unit s                                                           
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; print free                                                       
Model: SanDisk Cruzer Edge &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;scsi&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Disk /dev/sdb: 31266816s
Sector size &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;logical/physical&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start     End        Size       Type     File system  Flags
        32s       63s        32s                 Free Space
 1      64s       5854015s   5853952s   primary               boot, hidden
 2      5854016s  5983103s   129088s    primary  fat16
 3      5983104s  31266815s  25283712s  primary               lba

&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;3                                                             
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary 5983232s 100%                   
Warning: The resulting partition is not properly aligned &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;best performance.
Ignore/Cancel? Cancel                                                     
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary 5984256s 100%                                     
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; print free                                                       
Model: SanDisk Cruzer Edge &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;scsi&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Disk /dev/sdb: 31266816s
Sector size &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;logical/physical&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start     End        Size       Type     File system  Flags
        32s       63s        32s                 Free Space
 1      64s       5854015s   5853952s   primary               boot, hidden
 2      5854016s  5983103s   129088s    primary  fat16
        5983104s  5984255s   1152s               Free Space
 3      5984256s  31266815s  25282560s  primary               lba

&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; q                                                                
Information: You may need to update /etc/fstab.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;From the final output, we can see there is a big free space (1152 * 512B = 576 MB) between partition &lt;em&gt;2&lt;/em&gt; and &lt;em&gt;3&lt;/em&gt;. Of course, you can just leave 3rd partition unaligned considering the limited flash storage.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Initialize the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS&lt;/code&gt; encryption on the newly-created partition. You’ll be warned that this will overwrite any data on the partion. When prompted whether you want to proceed, type &lt;em&gt;YES&lt;/em&gt; (all upper case). Enter your selected passphrase (use &lt;em&gt;kali&lt;/em&gt; currently) twice when asked to do so.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# cryptsetup --verbose --verify-passphrase luksFormat /dev/sdb3
# cryptsetup luksOpen /dev/sdb3 my_usb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Format the &lt;em&gt;persistence&lt;/em&gt; partition &lt;em&gt;3&lt;/em&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ext4&lt;/code&gt; (the official reference use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ext3&lt;/code&gt;).&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkfs.ext4 -L persistence /dev/mapper/my_usb&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# e2label /dev/mapper/my_usb persistence, this step might be optional.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;This might take several minutes. Don&apos;t touch the keyboard!&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Create a mount point, mount our new encrypted partition there, set up the &lt;em&gt;persistence.conf&lt;/em&gt; file, and unmount the partition.&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkdir -p /mnt/usb&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount /dev/mapper/my_usb /mnt/usb&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# echo &quot;/ union&quot; &amp;gt; /mnt/usb/persistence.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# umount /dev/mapper/my_usb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Close the encrypted channel to our persistence partition.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# cryptsetup luksClose /dev/mapper/my_usb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Linux Distributions</title>
   <link href="/2015/07/22/linux-distrio/"/>
   <updated>2015-07-22T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/07/22/linux-distrio</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Linux kernel is the core of system management. We still need distributions to provide users a slightly high level interface. A Linux distribution is basically a wrapper of Linux kernel, supporting GUI, package management, etc.&lt;/p&gt;

    &lt;p&gt;You never notice Windows kernel thing since Windows is a complete system.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Common Linux distributions differ in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package management&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update method&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stable&lt;/code&gt; or not, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;security&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free&lt;/code&gt; or not etc. Refer to &lt;a href=&quot;http://program-think.blogspot.com/2013/10/linux-distributions-guide.html&quot;&gt;如何选择发行版&lt;/a&gt;
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Debian: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.deb&lt;/code&gt; package; stable.&lt;/p&gt;

        &lt;blockquote&gt;
          &lt;p&gt;Ubuntu, Mint.&lt;/p&gt;
        &lt;/blockquote&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Fedora: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rpm&lt;/code&gt; package.&lt;/p&gt;

        &lt;blockquote&gt;
          &lt;p&gt;RHEL (commercial use), CentOS (Community ENTerprise OS).&lt;/p&gt;
        &lt;/blockquote&gt;

        &lt;p&gt;&lt;img src=&quot;/assets/fedora.png&quot; alt=&quot;Relationship&quot; title=&quot;distrio diff&quot; /&gt;&lt;/p&gt;

        &lt;p&gt;CentOS derives from reverse engineering of RHEL, which takes away part of RHEL customers.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;OpenSUSE: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rpm&lt;/code&gt; built &lt;strong&gt;specialy&lt;/strong&gt; for openSUSE.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Arch Linux(KISS, binary package), Gentoo (source compiled locally)&lt;/p&gt;

        &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rolling release&lt;/code&gt; instead of normal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fix release&lt;/code&gt;. Need time and patience.&lt;/p&gt;

        &lt;p&gt;Arch Linux Wiki is the best in the world!&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;BackTrack, Kali&lt;/p&gt;

        &lt;p&gt;Based-on Debian now, focusing on security issue.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Package management, refer to &lt;a href=&quot;http://askubuntu.com/a/309121&quot;&gt;What is the difference between dpkg and aptitude/apt-get?&lt;/a&gt; and &lt;a href=&quot;http://how-to.linuxcareer.com/comparison-of-major-linux-package-management-systems&quot;&gt;Comparison of major Linux package management systems&lt;/a&gt;
    &lt;ol&gt;
      &lt;li&gt;Debian: .deb -&amp;gt; dpkg -&amp;gt; apt-get -&amp;gt; aptitude&lt;/li&gt;
      &lt;li&gt;Fedora: .rpm -&amp;gt; rpm -&amp;gt; yum&lt;/li&gt;
      &lt;li&gt;openSUSE: special .rpm -&amp;gt; rpm -&amp;gt; zypper&lt;/li&gt;
      &lt;li&gt;Arch: AUR binary -&amp;gt; pacman&lt;/li&gt;
      &lt;li&gt;Gentoo: portage source -&amp;gt; emerge (equery, eix)&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;They came up with a way to &lt;em&gt;store&lt;/em&gt; the files of an application in a &lt;em&gt;package&lt;/em&gt; so that it can be easily installed. So the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.deb&lt;/code&gt; package was born.&lt;/p&gt;

    &lt;p&gt;They needed a tool to install these &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.deb&lt;/code&gt; files, so they came up with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dpkg&lt;/code&gt; tool. This tool, however, will just install the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.deb&lt;/code&gt; file, but will not install its dependencies because it doesn&apos;t have those files and it does not have access to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;repositories&lt;/code&gt; to go pull the dependencies from.&lt;/p&gt;

    &lt;p&gt;Then, they came up with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get&lt;/code&gt;, which automates the problems in the previous point. Underneath the hood, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get&lt;/code&gt; is basically &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dpkg&lt;/code&gt; (so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get&lt;/code&gt; is a front-end for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dpkg&lt;/code&gt;), but a &lt;em&gt;clever&lt;/em&gt; one that will look for the dependencies and install them. It even looks at the currently installed dependencies and determines ones that are not being used by any other packages, and will inform you that you can remove them.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aptitude&lt;/code&gt; then came along, and it&apos;s nothing but a front-end UI for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apt-get&lt;/code&gt;. More difference refer to &lt;a href=&quot;http://unix.stackexchange.com/q/767&quot;&gt;what is difference between apt-get and aptitude&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Rumours&lt;/p&gt;

    &lt;p&gt;CentOS让RedHat招安了&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;Scientific Linux不还有吗。从来都不觉得CentOS有啥好的，package太老，连经常被嘲笑的Debian stable都看不下去了。稍微正常点用Ubuntu，文艺点用Arch Linux，CentOS没有了没什么大不了的&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;scientific linux你用过吗？我以前怀着希望试了一下，感觉用户群小的linux bug多啊。&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;CentOS更忠于RHEL原版, Scientific Linux自己改的东西多一些&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;这下估计 CentOS 要没有什么作为了。
 CentOS 的价值在于，提供一个开源并且可以直接预装的RHEL clone. RHEL 是很多企业的选择，因为他们想要超级稳定性，然后想要技术支持，例如，有了 zero day 的bug
 要赶紧补上。成熟的企业除非有特别强的Linux 背景，不是很感用随便的 distro。&lt;/p&gt;

    &lt;p&gt;RHEL 一直都在玩一个游戏就是，开源对吧。RHEL 提供src rpm。 但是 RHEL 不提供可以直接预装的 binary,只对商业用户提供。这个并没有违反开源的游戏规则。而且那个 RHEL 里面含有一些程序让别人不能直接复制那个 RHEL 的安装盘放到其他地区下载。同样，升级也需要是付费用户（有免费试用）。&lt;/p&gt;

    &lt;p&gt;CentOS 就是提供这样的服务，把 RHEL 的 src rpm，从新编译最后组装出 RHEL 兼容的但是大家可以随便使用的预装光盘。大家觉得不就是编译一下 src rpm 么，简单阿。其实不是那末简单。Redhat 的 src rpm 要编译出和 RHEL一样效果的 binary 需要用到 Redhat 的不开放的编译环境，还有很怪异的编译启动参数。这些参数是从编译环境直接传过来的。也就是说，CentOS提供的服务是逆向工程了RHEL的编译环境和捣鼓出安装光盘。相当与挖了 RH 的商业壁垒，挡人财路。&lt;/p&gt;

    &lt;p&gt;被招安之后，RH 当然不会干雇人来挖自己想保护的商业壁垒的蠢事。我猜结果就是，CentOS 估计要被阉割了。肯定不会完全消失，但是要用 CentOS 不爽。但是没有不爽到要有人舍得另起炉灶的地步。&lt;/p&gt;

    &lt;p&gt;类似的例子有 ntfs 3G. NTFS 3G 搞了个用户层的文件系统，就是为了保护他们商业版本的高性能 内核 NTFS 文件系统。这个方式很有效果，大多数人都比较慢的 ntfs 也行，所以搞个纯内核的NTFS 意义就小了很多。目前就没有人对着干。嵌入系统使用 NTFS，那个内核版本的可能还是比较合理的选择。&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;比如说哈，NSF 和 NIH 强调 open source，所以很多全国的大型计算中心在用 CentOS。这下子可就有大变动了。新的计算中心可能就要选 debian 了。&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;这是好事，centos的包都老掉牙了我觉得一般小地方的管理员就是为了所谓稳定，来个保守的选择centos，痛苦死了我很多东西都是自己local install的&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;RHEL/CentOS系只适合大企业内部养老，稍微正常点的公司都不会用。默认系统是稳定，但是很多包要么很老要么根本就没有需要自己找第三方源或者裸装，这样只要有非官方包进
 来，从根本上就破坏了它所谓的稳定，还不如用稍微正常点然后稳定和后续维护也还不错的Ubuntu LTS。激进和文艺一点的直接上Arch也没见出什么事&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;大公司用这个有，我个人观察比较大一个因素是推卸责任。人家不在乎没出什么事，那个是理所当然的。在乎的是出了事谁来背黑锅，可以推卸责任。所以比较像样的支持服务还
 是需要的。作为推卸责任的手段。“我们已经联系XXX公司在深入研究这个崩溃问题了，人家已经派最好的工程师在找原因…”。技术支持是推卸黑锅的很好办法，我已经用了技术
 好的公司了，那责任不在我这里，是那些公司不行。你要是自己用冷门的distro，万一了问题就要自己扛，不是开源没，自己动手改啊。自立更生。改不好啊，当初谁负责谁背黑
 锅。有技术实力的是不怕用比较新的系统的。 kernel.org 就是用fedora。人家流量也很大，一样跑得好好的。关键是里面有牛人，有问题自己能消化。&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;唉唉，在法律责任切分严格的行业，RHEL 还是有压倒性的优势的。比如说医疗系统。我们这里搭个 cluster，我说上 debian，IT 
 直接就问：出了问题算谁的？谁来承担责任并且走人？再比如说，我们这里上了一套数据库系统，因为先期投入大，造成去年预算问题，信用等级被降级，CIO 立刻走人。&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;嗯嗯，是啊是啊。我们这里 IT 说他们有雇员有RH的认证，所以有资质使用RHEL。买大些的东西，首先看的就是出了问题后，如何确定责任。
 每个人都只会支持那些让自己的职业比较安全的东西，这是底线。好不好则另说了。&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;企业端不用RHEL/CentOS的只怕不多。&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;For those that are saying Red Hat is the main project, yes it is.. But the diagram shows how the flow actually goes. Red Hat are based on stable packages of Fedora, not that Red Hat is Fedora&apos;s derivatives. CentOS however, is the stable release of Red Hat for the community. What we don&apos;t see here is that Red Hat uses both Fedora and CentOS for its experiments and stability testings to improve Red Hat, which is genius. This contributes for the corporate highly stable release of Linux, which is one of the best OS around.&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;Fedora is the starting point. Those packages eventually make it into RHEL once they are proven to be stable. Then the RHEL Source code is used to create CentOS without the RHEL branding.&lt;/p&gt;

    &lt;hr /&gt;
    &lt;p&gt;From a corporate point of view Red Hat is the main project that Red Hat throws the amount of resources. and the one that brings the revenue. However, as others have said, on a technical level, and as the diagram depicts. Fedora flows into Red Hat and Red Hat flows into CentOS&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Kali ABC</title>
   <link href="/2015/07/22/kali/"/>
   <updated>2015-07-22T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/07/22/kali</id>
   <content type="html">&lt;p&gt;First attempt to launch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kali&lt;/code&gt; system with some basic ideas. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kali&lt;/code&gt; originates from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BackTrack &lt;/code&gt; which is no longer maintained.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.kali.org/&quot;&gt;Kali&lt;/a&gt; is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Debian&lt;/code&gt;-based distribution devoted to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Penetration Testing&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;&quot;the quieter you become, the more you are about to hear&quot;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Kali&lt;/code&gt; in &lt;em&gt;VMWare&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Choose customized VMWare images offered by &lt;a href=&quot;https://www.offensive-security.com/kali-linux-vmware-arm-image-download/&quot;&gt;offensive-security&lt;/a&gt; instead of the official ISO. Just extract the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;7z&lt;/code&gt; image and launch it from VMWare.&lt;/p&gt;

    &lt;p&gt;The default &lt;em&gt;root&lt;/em&gt; password is &lt;em&gt;toor&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Boot warning:&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;em&gt;not starting portmapper is not running&lt;/em&gt;, refer to &lt;a href=&quot;http://www.blackmoreops.com/2013/11/18/fix-starting-portmapper-running-warning-debian-kali-linux/&quot;&gt;How to fix 1&lt;/a&gt; and &lt;a href=&quot;https://forums.kali.org/showthread.php?1323-not-starting-portmapper-is-not-running-(warning)&quot;&gt;#17 floor&lt;/a&gt;&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# update-rc.d -f nfs-common remove&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;em&gt;PulseAudio configured for per-user sessions Warning&lt;/em&gt;, refer to &lt;a href=&quot;http://forums.debian.net/viewtopic.php?f=10&amp;amp;t=89120&quot;&gt;not an issue&lt;/a&gt;&lt;/p&gt;

        &lt;p&gt;This is not actually an real issue. The real issue lies in the warning message itself.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Git Configuration</title>
   <link href="/2015/07/19/git-configuration/"/>
   <updated>2015-07-19T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/07/19/git-configuration</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#installation&quot; id=&quot;markdown-toc-installation&quot;&gt;Installation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configuration&quot; id=&quot;markdown-toc-configuration&quot;&gt;Configuration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#gitignore&quot; id=&quot;markdown-toc-gitignore&quot;&gt;Gitignore&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Install&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -av dev-vcs/git&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;touch ~/.config/git/config&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;If you&apos;d like a per-user config, create this file first.&lt;/p&gt;

    &lt;p&gt;In Gentoo Xfce4, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$XDG_CONFIG_HOME&lt;/code&gt; is not set by default. Without touching this file manually, it would defaults to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gitconfig&lt;/code&gt; instead.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --system user.name  &quot;&amp;lt;username&amp;gt;&quot;&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;Specify a name so your commits will be properly labeled. It can be anything that is meaningful to you.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --system user.email &quot;&amp;lt;id+username&amp;gt;@users.noreply.github.com&quot;&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;Tell Git the email address that will be associated with your Git commits. The email you specify should be the same one found in your email settings. To keep your email address hidden, see &lt;a href=&quot;https://help.github.com/articles/keeping-your-email-address-private/&quot;&gt;Keeping your email address private&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --system core.editor emc&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;You can configure the default text editor that will be used when Git needs you to type in a message (without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-m&lt;/code&gt; opton on push). If not configured, Git uses your system’s default editor, which is generally one of Vim, Emacs and Nano.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --system credential.helper &apos;cache --timeout=3600&apos;&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;If you&apos;re &lt;a href=&quot;https://help.github.com/articles/which-remote-url-should-i-use&quot;&gt;managing GitHub repositories using HTTPS&lt;/a&gt; due to SSH blocked by company firewall, you can use a &lt;em&gt;credential helper&lt;/em&gt; to tell Git to &lt;a href=&quot;https://stackoverflow.com/q/5343068&quot;&gt;remember&lt;/a&gt; your GitHub username, password or API token for a while every time it talks to GitHub. By default, Git will cache your password for 15 minutes (900 seconds).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --system push.default simple&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;For EOL conversion, refer to &lt;a href=&quot;/2014/09/08/git-line-ending-conversion/&quot;&gt;git line ending conversion&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --system -l&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;Check current config.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;For a single user system, you&apos;d best use &lt;em&gt;–system&lt;/em&gt; instead of &lt;em&gt;–global&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;gitignore&quot;&gt;Gitignore&lt;/h1&gt;

&lt;p&gt;For language-specific ignorance, refer to &lt;a href=&quot;https://github.com/github/gitignore&quot;&gt;A collection of useful .gitignore templates&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Two consective stars followed by a slash (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**/&lt;/code&gt;) means to match all directories. Without the trailing slash, to match anything regardless of files or directories.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ignore name &apos;foo&apos;
**/foo
# equivalent to:
foo

# ignore name &apos;bar&apos; under directory &apos;foo&apos;
**/foo/bar

# ignore anything under directory &apos;foo&apos;
foo/**
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;All patterns are relative to the location of the &lt;em&gt;.gitignore&lt;/em&gt; file unless a leading slash is provided.&lt;/li&gt;
      &lt;li&gt;Without trailing slash, a name can match a file or a directory.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Ignore a directory but a file.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;my-dir/**
!my-dir/my-file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The consecutive stars &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**&lt;/code&gt; is to improve performance. Another way to solve this issue is creating a new &lt;em&gt;.gitignore&lt;/em&gt; under &lt;em&gt;my-dir&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# my-dir/.gitignore
   
*
!.gitignore
   
!my-file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The newly created &lt;em&gt;.gitignore&lt;/em&gt; has higher priority over those in uppper directories.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/ignore&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;This is the global &lt;em&gt;ignore&lt;/em&gt; list that applys to all Git repositories for current user.&lt;/p&gt;

    &lt;p&gt;For example, on my Gentoo:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;*~
.#*
\#*\#
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The first line ignores Linux file auto-backup. The next two lines are for Emacs eidtor&apos;s backup.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If a file or directory is accidently pushed to remote repository, you decide to remove that later on.&lt;/p&gt;

    &lt;p&gt;Firstly, create a &lt;em&gt;.gitignore&lt;/em&gt; file. Put patterns there to ignore unwanted names.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cached&lt;/span&gt; name&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;remove name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; git push
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Cronie and Anacron</title>
   <link href="/2015/07/19/cronie/"/>
   <updated>2015-07-19T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/07/19/cronie</id>
   <content type="html">&lt;p&gt;&lt;em&gt;cron&lt;/em&gt; automates taks sheduling at specific time. There are many different implementations of which I choose &lt;em&gt;cronie&lt;/em&gt; with &lt;em&gt;anacron&lt;/em&gt; USE flag enabled. It accomplishes this task by waking up &lt;em&gt;every minute&lt;/em&gt; and checking to see if there are any cron-jobs to run in any of the user crontabs.&lt;/p&gt;

&lt;p&gt;It is basically for servers that won&apos;t shutdown. Sheduled tasks would &lt;em&gt;not&lt;/em&gt; be ran if the machine is powered off at the exact sheduled time. &lt;em&gt;anacron&lt;/em&gt; however, does not assume the machine is running continuously. &lt;em&gt;anacron&lt;/em&gt; usually relies on another &lt;em&gt;cron&lt;/em&gt; daemon (i.e. &lt;em&gt;cronie&lt;/em&gt;) and executes commands at intervals specified in day. It will run missed jobs upon startup.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# echo &apos;sys-process/cronie anacron&apos; &amp;gt; /etc/portage/package.use/cronie (opt)&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# emerge -avt virtual/cron&lt;/span&gt;
root@tux ~ &lt;span class=&quot;c&quot;&gt;# rc-update add cronie default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;cronie&lt;/em&gt; has built-in &lt;em&gt;anacron&lt;/em&gt; feature that is optionally now.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;cronie&lt;/em&gt; schedules locates in &lt;em&gt;/etc/crontab&lt;/em&gt; and &lt;em&gt;/etc/cron.d/&lt;/em&gt;, while &lt;em&gt;anacron&lt;/em&gt; in &lt;em&gt;/etc/anacrontab&lt;/em&gt;. Like most other &lt;em&gt;cron&lt;/em&gt; daemons, &lt;em&gt;cronie&lt;/em&gt; depends on &lt;em&gt;sys-process/cronbase&lt;/em&gt; whose jobs in &lt;em&gt;/etc/cron.{daily,hourly,weekly,monthly}&lt;/em&gt;. So we have three &lt;em&gt;cron&lt;/em&gt; components, namely &lt;em&gt;cronbase&lt;/em&gt;, &lt;em&gt;cronie&lt;/em&gt;, and &lt;em&gt;anacron&lt;/em&gt; which can be combined to meet our job schedule requirements.&lt;/p&gt;

&lt;p&gt;All those above are system-wide schedules and we can &lt;em&gt;manually&lt;/em&gt; edit those files. We define user schedules with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crontab&lt;/code&gt; command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux ~ &lt;span class=&quot;c&quot;&gt;# crontab [ -u USER ] [ -l | -e | -r ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crontab&lt;/code&gt; command does not handle system-wide schedules. Without explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-u&lt;/code&gt; argument, it defaults to &lt;em&gt;root&lt;/em&gt; account. It edits (or creates) file &lt;em&gt;/var/spool/cron/conrtabs/${USER}&lt;/em&gt;. File name is the same as user account name. When executing commands under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;su&lt;/code&gt; you should always use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-u&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;The built-in &lt;em&gt;anacron&lt;/em&gt; feature does not bring in command line to edit &lt;em&gt;/etc/anacrontab&lt;/em&gt;. Like system-wide schedules, &lt;em&gt;anacron&lt;/em&gt; schedules should be updated manually.&lt;/p&gt;

&lt;p&gt;Let&apos;s have a look at the default system-wide schedules. In &lt;em&gt;/etc/crontab&lt;/em&gt;, we found:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;59  *  * * *    root    rm -f /var/spool/cron/lastrun/cron.hourly
9  3  * * *     root    rm -f /var/spool/cron/lastrun/cron.daily
19 4  * * 6     root    rm -f /var/spool/cron/lastrun/cron.weekly
29 5  1 * *     root    rm -f /var/spool/cron/lastrun/cron.monthly
*/10  *  * * *  root    test -x /usr/sbin/run-crons &amp;amp;&amp;amp; /usr/sbin/run-crons
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;cronie&lt;/em&gt; daemon runs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run-crons&lt;/code&gt; script (comes with &lt;em&gt;cronbase&lt;/em&gt;) every 10 minutes. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run-crons&lt;/code&gt; looks into */etc/cron.[hourly&lt;/td&gt;
      &lt;td&gt;daily&lt;/td&gt;
      &lt;td&gt;weekly&lt;/td&gt;
      &lt;td&gt;monthly]* for scripts to be executed. For example, &lt;em&gt;/etc/cron.daily/logrotate&lt;/em&gt;.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The schedules above gurantee jobs got ran even if the computer was off when they were scheduled to run. Details can be checken from &lt;em&gt;run-crons&lt;/em&gt; script. Therefore, there is no need to enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anacron&lt;/code&gt; USE.&lt;/p&gt;

&lt;p&gt;Specially, we found &lt;em&gt;/etc/cron.hourly/0anacron&lt;/em&gt; script. That is to say:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;cronie&lt;/em&gt; triggers &lt;em&gt;cronbase&lt;/em&gt;&apos;s hourly job &lt;em&gt;0anacron&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the tail of &lt;em&gt;0anacron&lt;/em&gt;,  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anacron -s&lt;/code&gt; handles schedules defined &lt;em&gt;/etc/anacrontab&lt;/em&gt;. Different from &lt;em&gt;cronie&lt;/em&gt; that schedules jobs at fixed time , &lt;em&gt;anacron&lt;/em&gt; schedules to run jobs every other days (day, week, month).&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;*/etc/cron.[daily&lt;/td&gt;
      &lt;td&gt;weekly&lt;/td&gt;
      &lt;td&gt;monthly]* will be ran twice by &lt;em&gt;cronie&lt;/em&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run-crons&lt;/code&gt;) and &lt;em&gt;anacron&lt;/em&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;run-parts&lt;/code&gt;) at different times, leading to possible double job executions.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Either remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anacron&lt;/code&gt; USE or comment out any overlapping entries from &lt;em&gt;/etc/crontab&lt;/em&gt; or &lt;em&gt;/etc/anacrontab&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Before a user can access to &lt;em&gt;crontab&lt;/em&gt;, he must be in &lt;em&gt;cron&lt;/em&gt; group by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gpasswd -a username cron&lt;/code&gt;. Then we update */etc/cron.{allow, deny}:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/cron.deny
all

# /etc/cron.allow
username
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With this setting, all users (except &lt;em&gt;root&lt;/em&gt;) by default cannot access to &lt;em&gt;crontab&lt;/em&gt;. We grant access by adding user name to &lt;em&gt;cron.allow&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Cron#Cronie&quot;&gt;arch wiki cron&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Cron&quot;&gt;gentoo wiki cron&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bugs.gentoo.org/show_bug.cgi?id=538864&quot;&gt;bug 538864&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.nico.schottelius.org/blog/how-cronie-anacron-cron-hourly-daily-weekly-work/&quot;&gt;how cronie anacron hourly daily weekly work&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bbs.archlinux.org/viewtopic.php?id=118104&quot;&gt;Cronie changes&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>sed awk</title>
   <link href="/2015/06/12/sed-awk/"/>
   <updated>2015-06-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/06/12/sed-awk</id>
   <content type="html">&lt;p&gt;These tools do a big favor when editing streams. Both programs use regular expressions for selecting and processing text.&lt;/p&gt;

&lt;p&gt;For instance, a configuration file contains lots of comment lines starting with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt; and blank lines. When applying the configuration to systems, you might need to remove those lines for a clean and tidy configuration file.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sed &apos;/^ *#/d&apos; nginx_with_comments.conf | sed &apos;/^$/d&apos; &amp;gt; nginx.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt;(&lt;em&gt;stream editor&lt;/em&gt;, take pipes as input) command to &lt;em&gt;delete&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; specific pattern lines. The 1st part removes comment lines while the 2nd remove blank lines.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt;  considers each file as a set of records, which by default are the lines in the file. &quot;awk&quot; enables you to create a condition and action pair, and for each record that matches the condition, the action will fire. Most &quot;awk&quot; commands follow this pattern – you have a condition, followed by an action in curly braces.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ls -al ~/ | awk &apos;/zachary/{print $1, $9}&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command will first file lines contain &lt;em&gt;zachary&lt;/em&gt; and then print the 1st and 8th items/columns - to print permissions and filenames. &lt;strong&gt;awk is really useful when dealing with columns&lt;/strong&gt;. You can use other conditions; for example, checking whether or not a certain field is above or below a given threshold (i.e. $5 &amp;gt; 2), or checking whether a record has a certain column.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ls -al | awk &apos;$9 ~/^\./ {gsub(/zachary/, &quot;awkSub&quot;); print;}&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;akw&lt;/code&gt; check wheter the 9th item (filename) starts wity dot. Then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gsub&lt;/code&gt; (&lt;em&gt;global substitute&lt;/em&gt;) to substitue every occurence of &lt;em&gt;zachary&lt;/em&gt; with &lt;em&gt;awkSub&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;awk-vs-sed&quot;&gt;awk VS sed&lt;/h1&gt;

&lt;p&gt;Both are tools that transform text. BUT &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt; can do more things besides just manipulating text. Its a programming language by itself with most of the things you learn in programming, like arrays, loops, if/else flow control etc You can &quot;program&quot; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; as well, but you won&apos;t want to maintain the code written in it.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; is a &lt;strong&gt;stream editor&lt;/strong&gt;. It works with &lt;strong&gt;streams of characters&lt;/strong&gt; on a &lt;strong&gt;per-line&lt;/strong&gt; basis. It has a primitive programming language that includes goto-style loops and simple conditionals (in addition to pattern matching and address matching). There are essentially only two &quot;variables&quot;: pattern space and hold space. Readability of scripts can be difficult. Mathematical operations are extraordinarily awkward at best.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt; is oriented toward &lt;strong&gt;delimited fields&lt;/strong&gt; on a &lt;strong&gt;per-line&lt;/strong&gt; basis. It has much more &lt;strong&gt;robust programming&lt;/strong&gt; constructs including &lt;strong&gt;if/else&lt;/strong&gt;, &lt;strong&gt;while&lt;/strong&gt;, &lt;strong&gt;do/while&lt;/strong&gt; and &lt;strong&gt;for&lt;/strong&gt; (C-style and array iteration). There is complete support for variables and single-dimension associative arrays plus (IMO) kludgey multi-dimension arrays. Mathematical operations resemble those in C. It has printf and functions. The &quot;K&quot; in &quot;AWK&quot; stands for &quot;&lt;em&gt;K&lt;/em&gt;ernighan&quot; as in &quot;Kernighan and Ritchie&quot; of the book &quot;C Programming Language&quot; fame (not to forget &lt;em&gt;A&lt;/em&gt;ho and &lt;em&gt;W&lt;/em&gt;einberger). One could conceivably write a detector of academic plagiarism using awk.&lt;/p&gt;

&lt;p&gt;I would tend to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; where there are patterns in the text. For example, you could replace all the negative numbers in some text that are in the form &quot;minus-sign followed by a sequence of digits&quot; (e.g. &quot;-231.45&quot;) with the &quot;accountant&apos;s brackets&quot; form (e.g. &quot;(231.45)&quot;) using this (which has room for improvement):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;echo &quot;-123.456 -345.678&quot; sed &apos;s/-\([0-9.]\+\)/(\1)/g&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I would use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt; when the text looks more like rows and columns or, as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt; refers to them &quot;records&quot; and &quot;fields&quot; - matrix. Refer to the example above.&lt;/p&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; for very simple text parsing. Anything beyond that, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt; is better. In fact, you can ditch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sed&lt;/code&gt; altogether and just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt;. Since their functions overlap and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt; can do more, just use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;awk&lt;/code&gt;. You will reduce your learning curve as well.&lt;/p&gt;

&lt;p&gt;总之，sed能实现的awk也能实现；简单的模式匹配用awk；有矩阵行列特征用awk。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>library soname</title>
   <link href="/2015/06/07/shared-library-soname/"/>
   <updated>2015-06-07T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/06/07/shared-library-soname</id>
   <content type="html">&lt;p&gt;In Unix operating systems, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;soname&lt;/code&gt; is a field of data in a shared object file. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;soname&lt;/code&gt; is a string, which is used as a &quot;logical name&quot; describing the functionality of the object.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;soname&lt;/code&gt; is often used to provide version &lt;strong&gt;backwards-compatibility&lt;/strong&gt; information. For instance, if versions 1.0 through 1.9 of the shared library libx provide identical interface, they would all have the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;soname&lt;/code&gt;, e.g. &lt;em&gt;libx.so.1&lt;/em&gt;. If the system only includes version 1.3 of that shared object, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filename&lt;/code&gt; &lt;em&gt;libx.so.1.3&lt;/em&gt;, the &lt;em&gt;soname&lt;/em&gt; field of the shared object tells the system that it can be used to fill the dependency for a binary which was originally compiled using version 1.2.&lt;/p&gt;

&lt;p&gt;Linux 系统，也同样面临和Window一样的问题，如何控制动态库的多个版本问题。Window之前没有处理好，为此专门有个名词来形容这个问题 “Dll hell”，其严重影响软件的升级和维护。 Dll hell 是指windows 上动态库新版本覆盖旧版本，﻿﻿但是却不兼容老版本。常常发生在程序升级之后，动态库更新，原有程序运行不起来；或者装新软件，但是已有的软件运行不起来。 同样Linux操作系统，也有同样的问题，那么它是怎么解决的呢？&lt;/p&gt;

&lt;p&gt;Linux 为解决这个问题，引入了一套机制，如果遵守这个机制来做，就可以避免这个问题。 但是这只事一个约定，不是强制的。但是建议遵守这个约定，否则同样也会出现 Linux 版的Dll hell 问题。 下面来介绍一个这个机制。 这个机制是通过文件名，来控制dll （shared library） 的版本。&lt;/p&gt;

&lt;p&gt;Linux 上的Dll ，叫shared library，其有三个名字，分别又不同的目的。&lt;/p&gt;

&lt;p&gt;Every shared library has a special name called the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;soname&lt;/code&gt;. The soname has the prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib&lt;/code&gt;, the name of the library, the phrase &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.so&lt;/code&gt;, followed by a period and a version number that is incremented whenever the interface changes (as a special exception, the lowest-level C libraries don&apos;t start with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib&lt;/code&gt;). A fully-qualified soname includes as a prefix the directory it&apos;s in; on a working system a fully-qualified soname is simply a symbolic link to the shared library&apos;s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;real name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Every shared library also has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;real name&lt;/code&gt;, which is the filename containing the actual library code. The real name adds to the soname a period, a minor number, another period, and the release number. The last period and release number are optional. The minor number and release number support configuration control by letting you know exactly what version(s) of the library are installed. Note that these numbers might not be the same as the numbers used to describe the library in documentation, although that does make things easier.&lt;/p&gt;

&lt;p&gt;In addition, there&apos;s the name that the compiler uses when requesting a library, (I&apos;ll call it the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linker name&lt;/code&gt;), which is simply the soname without any version number.&lt;/p&gt;

&lt;p&gt;The key to managing shared libraries is the separation of these names. Programs, when they internally list the shared libraries they need, should only list the soname they need. Conversely, when you create a shared library, you only create the library with a specific filename (with more detailed version information). When you install a new version of a library, you install it in one of a few special directories and then run the program ldconfig(8). ldconfig examines the existing files and creates the sonames as symbolic links to the real names, as well as setting up the cache file /etc/ld.so.cache (described in a moment).&lt;/p&gt;

&lt;p&gt;ldconfig doesn&apos;t set up the linker names; typically this is done during library installation, and the linker name is simply created as a symbolic link to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latest&lt;/code&gt; soname or the latest real name. I would recommend having the linker name be a symbolic link to the soname, since in most cases if you update the library you&apos;d like to automatically use it when linking. I asked H. J. Lu why ldconfig doesn&apos;t automatically set up the linker names. His explanation was basically that you might want to run code using the latest version of a library, but might instead want development to link against an old (possibly incompatible) library. Therefore, ldconfig makes no assumptions about what you want programs to link to, so installers must specifically modify symbolic links to update what the linker will use for a library.&lt;/p&gt;

&lt;p&gt;Thus, /usr/lib/libreadline.so.3 is a fully-qualified soname, which ldconfig would set to be a symbolic link to some realname like /usr/lib/libreadline.so.3.0. There should also be a linker name, /usr/lib/libreadline.so which could be a symbolic link referring to /usr/lib/libreadline.so.3.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;real name: libmath.so.1.1.1234&lt;/p&gt;

    &lt;p&gt;lib + name + .so + .major number + .minor number + .release number&lt;/p&gt;

    &lt;p&gt;主板号，代表当前动态库的版本，就是共享库文件本身的文件名，里面是共享库的代码。&lt;strong&gt;如果动态库的接口有变化，那么这个版本号就要加1&lt;/strong&gt;；后面的两个版本号（小版本号 和 build 号）是告诉你详细的信息，比如为一个hot-fix 而生成的一个版本，其小版本号加1，build号也应有变化。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;soname: libmath.so.1
动态库的soname，其是应用程序加载共享库时，帮助寻找共享库用的文件名。其格式为:&lt;/p&gt;

    &lt;p&gt;lib + name +.so + .major number&lt;/p&gt;

    &lt;p&gt;其只包含major version number，换句话说，也就是只要其接口没有变，应用程序都可以用，不管你其后minor build version or build version。soname通常存在于几个地方：作为软链接指向real name；存放在共享库本身的文件头部header；存放在应用程序的头部共享库声明部分。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;linker name: libmath.so&lt;/p&gt;

    &lt;p&gt;lib + name + .so&lt;/p&gt;

    &lt;p&gt;连接名（linker name），是专门为应用程序在链接link阶段找到共享库而设置的指向soname或这real name的软链接，一般在系统安装共享库时，系统会自动创建，通常默认应该指向系统里&lt;strong&gt;最新的&lt;/strong&gt;soname or real name。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在共享库编译过程中，连接（link） 阶段，编译器将生成一个共享库及real name，同时将共享库的soname，写在共享库文件里的文件头里面。可以用命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;readelf -d libmath.so.1.1.1234&lt;/code&gt; 去查看。在应用程序编译阶段，引用共享库时，其会用到共享库的linker name，其通过linker name 找到最新的动态库库文件，并且把共享库的soname提取出来，写在自己的共享库的头里面。当应用程序加载时候就会通过soname软链接去在给定的路径下寻找该共享库。&lt;/p&gt;

    &lt;p&gt;libmath.so -&amp;gt; libmath.so.1 -&amp;gt; libmath.so.1.1.1234&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;linker name是link阶段找到最新共享库版本服务的&lt;/strong&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;共享库小版本升级&quot;&gt;共享库小版本升级&lt;/h2&gt;

&lt;p&gt;当升级小版本时，即接口不变。共享库的soname是不变的，所以需要重新把soname的那个连接文件指定新版本就可以。 调用ldconfig命令，系统会帮你做修改那个soname link文件，并把它指向新的版本呢。这时候你的应用程序就自动升级了。&lt;/p&gt;

&lt;h2 id=&quot;共享库主版本升级&quot;&gt;共享库，主版本升级&lt;/h2&gt;

&lt;p&gt;即接口发生变化，这是共享库的soname发生了变化。如果多个版本的共享库并存，那么就多多个soname 分别链接到对应的real name，而linker name总是指向最新的那个real name。&lt;/p&gt;

&lt;p&gt;Reference &lt;a href=&quot;http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html&quot;&gt;shared-libraries&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Environment Variable</title>
   <link href="/2015/06/07/environmental-variables/"/>
   <updated>2015-06-07T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/06/07/environmental-variables</id>
   <content type="html">&lt;p&gt;In Unix-like systems, we have to deal with environment variables such as PATH, MANPATH etc. Here are some &lt;a href=&quot;http://mywiki.wooledge.org/DotFiles&quot;&gt;tips&lt;/a&gt; for reference.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Order of directory&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;:~/opt/bin
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/opt/bin:&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The diffeence of the two lines is the order when searching for commands. The 2nd line make directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/opt/bin&lt;/code&gt; searched before those ones in original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt; or not&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;:~/opt/bin
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;:~/opt/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt; is a shell builtin for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ksh&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zsh&lt;/code&gt;.  The first line omit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt; keyword which is called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assignment&lt;/code&gt;. We don&apos;t need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt; if the variable is already in the environment: any change of the value of the variable is reflected in the environment for modern shells. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt; is pretty much always in the environment; all Unix-like system sets it in the very beginning (usually in the very first process, in fact).&lt;/p&gt;

    &lt;p&gt;But if the variable is not in the environment, you must add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt;. For example, some environment variable is for specific program newly installed. You could test by command:&lt;/p&gt;

    &lt;p&gt;```bash
~ $ declare -p VAR_NAME&lt;/p&gt;

    &lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export&lt;/code&gt; if not sure.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/bin
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;:~/bin
&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:~/bin&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The last line does not work*. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; character is only expanded to your home directory when it&apos;s the first character of a word and it&apos;s unquoted. For the last line, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; is between double quotes and therefore not expanded. Even if you wrote &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export &quot;PATH=$PATH:&quot;~/Unix/homebrew/bin&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; would not be expanded because it is not at the beginning of a shell word.&lt;/p&gt;

    &lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Double quotes or not&lt;/p&gt;

    &lt;p&gt;If you have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; in variable settings, omit double quotes. In all other cases, this does not matter.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.profile&lt;/code&gt; is the place to put stuff that applies to your &lt;strong&gt;whole session&lt;/strong&gt; of a &lt;em&gt;login&lt;/em&gt; shell (like &lt;em&gt;zsh&lt;/em&gt;), such as programs that you want to start when you log in (but not graphical programs, they go into a different file, i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.xinitrc&lt;/code&gt;), and environment variable definitions. For Bash shell, we have a counterpart &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bash_profile&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; is the place to put stuff that applies only to Bash only, such as alias and function definitions, shell options, and prompt settings. (You could also put key bindings there, but for bash they normally go into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.inputrc&lt;/code&gt;.)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bash_profile&lt;/code&gt; can be used instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.profile&lt;/code&gt;, but it is Bash&apos;s alternative of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.profile&lt;/code&gt;, not used by any other shell. (This is mostly a concern if you want your initialization files to work on multiple machines and your login shell isn&apos;t bash on all of them.) This is a logical place to include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; if the shell is interactive.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Set up your environment (PATH, LANG, EDITOR, …) in &quot;~/.bash_profile&quot;. Set up your bash shell (PS1, functions, shopts, …) in &quot;~/.bashrc&quot;. Then source &quot;.bashrc&quot; from &quot;.bash_profile&quot;.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Check &lt;a href=&quot;https://mywiki.wooledge.org/DotFiles&quot;&gt;dotfiles&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You may see here and there recommendations to either put environment variable definitions in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; or always launch login shells in terminals. Both are bad ideas. The most common problem with either of these ideas is that your environment variables will only be set in programs launched via the terminal, not in programs started directly with an icon or desktop menu or keyboard shortcut.&lt;/p&gt;

    &lt;p&gt;But in Gentoo, the official Wiki recommends per-user setting in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; which is sourced by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bash_profile&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bash_profile&lt;/code&gt; is executed for login shells, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; is executed for interactive non-login shells. When you login (eg: type username and password) via console, either physically sitting at the machine when booting, or remotely via ssh: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bash_profile&lt;/code&gt; is executed to configure things before the initial command prompt. But, if you&apos;ve already logged into your machine and open a new terminal window (xterm) inside Gnome or KDE, then .bashrc is executed before the window command prompt. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; is also run when you start a new bash instance by typing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/bin/bash&lt;/code&gt; in a terminal.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Execution order:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Login shell: /etc/profile -&amp;gt; /etc/env.d/* -&amp;gt; /etc/bash/bashrc -&amp;gt; /etc/profile.d/*.sh -&amp;gt; ~/.bash_profile -&amp;gt; ~/.bashrc&lt;/p&gt;

      &lt;p&gt;Interactive shell: /etc/bash/bashrc -&amp;gt; ~/.bashrc&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;References: &lt;a href=&quot;http://unix.stackexchange.com/a/26059&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;http://superuser.com/a/183980&quot;&gt;2&lt;/a&gt; and &lt;a href=&quot;http://unix.stackexchange.com/a/25704&quot;&gt;3&lt;/a&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Shell特殊变量：Shell $0, $#, $*, $@, $?, $$和命令行参数</title>
   <link href="/2015/06/05/shell-special-argument/"/>
   <updated>2015-06-05T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/06/05/shell-special-argument</id>
   <content type="html">&lt;p&gt;Shell 中变量名只能包含数字、字母和下划线，因为某些包含其他字符的变量有特殊含义，这样的变量被称为特殊变量。&lt;/p&gt;

&lt;p&gt;例如，$ 表示当前Shell进程的ID，即pid，看下面的代码：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;$&lt;/em&gt; echo $$&lt;/p&gt;
&lt;/blockquote&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;变量&lt;/th&gt;
      &lt;th&gt;含义&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;$0&lt;/td&gt;
      &lt;td&gt;当前脚本的文件名&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$n&lt;/td&gt;
      &lt;td&gt;传递给脚本或函数的参数。n 是一个数字，表示第几个参数。例如，第一个参数是$1，第二个参数是$2。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$#&lt;/td&gt;
      &lt;td&gt;传递给脚本或函数的参数个数。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$*&lt;/td&gt;
      &lt;td&gt;传递给脚本或函数的所有参数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$@&lt;/td&gt;
      &lt;td&gt;传递给脚本或函数的所有参数。被双引号(&quot; &quot;)包含时，与 $* 稍有不同，下面将会讲到。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$?&lt;/td&gt;
      &lt;td&gt;上个命令的退出状态，或函数的返回值。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$$&lt;/td&gt;
      &lt;td&gt;当前Shell进程ID。对于 Shell 脚本，就是这些脚本所在的进程ID。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;-和--的区别&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$*&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$@&lt;/code&gt; 的区别&lt;/h1&gt;

&lt;p&gt;$* 和 $@ 都表示传递给函数或脚本的所有参数，不被双引号(&quot; &quot;)包含时，都以&quot;$1&quot; &quot;$2&quot; … &quot;$n&quot; 的形式输出所有参数。&lt;/p&gt;

&lt;p&gt;但是当它们被双引号(&quot; &quot;)包含时，&quot;$*&quot; 会将所有的参数作为一个整体，以&quot;$1 $2 … $n&quot;的形式输出所有参数；&quot;$@&quot; 会将各个参数分开，以&quot;$1&quot;, &quot;$2&quot;, …,&quot;$n&quot; 的形式输出所有参数。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Filesystem Hierarchy Standard</title>
   <link href="/2015/06/04/filesystem-hierarchy-standard/"/>
   <updated>2015-06-04T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/06/04/filesystem-hierarchy-standard</id>
   <content type="html">&lt;p&gt;[The Filesystem Hierarchy Standard (FHS)][1] defines the directory structure and directory contents in Unix and Unix-like operating systems, maintained by the Linux Foundation. The current version is 3.0, released on 3 June 2015.&lt;/p&gt;

&lt;p&gt;This command will give you a brief description on FHS:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;$&lt;/em&gt; man hier&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We focus on some directories relevant to binaries.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Directory&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;/&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;Primary hierarchy&lt;/strong&gt; root and root directory of the entire file system hierarchy.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/bin&lt;/td&gt;
      &lt;td&gt;This directory contains executable programs which are needed in single user mode and to bring the system up or repair it. Essential command binaries that need to be available in single user mode; for all users, e.g., cat, ls, cp. For binaries usable before the /usr partition is mounted. This is used for trivial binaries used in the very early boot stage or ones that you need to have available in booting single-user mode.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/sbin&lt;/td&gt;
      &lt;td&gt;Like /bin, this directory holds commands needed to boot the system, but which are usually not executed by normal users. Essential system binaries, e.g., init, ip, mount.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/usr&lt;/td&gt;
      &lt;td&gt;This directory is usually mounted from a separate partition. It should hold only sharable, read-only data, so that it can be mounted by various machines running Linux. &lt;strong&gt;Secondary hierarchy&lt;/strong&gt; for read-only user data; contains the majority of (multi-)user utilities and applications.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/usr/bin&lt;/td&gt;
      &lt;td&gt;This is the primary directory for executable programs. Most programs executed by normal users which are not needed for booting or for repairing the system and which are not installed locally should be placed in this directory. Non-essential command binaries (not needed in single user mode); for all users.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/usr/sbin&lt;/td&gt;
      &lt;td&gt;This directory contains program binaries for system administration which are not essential for the boot process, for mounting /usr, or for system repair. Non-essential system binaries, e.g., daemons for various network-services.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/usr/local&lt;/td&gt;
      &lt;td&gt;This is where programs which are local to the site typically go. &lt;strong&gt;Tertiary hierarchy&lt;/strong&gt; for local data, specific to this host. Typically has further subdirectories, e.g., bin/, lib/, share.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/usr/local/bin&lt;/td&gt;
      &lt;td&gt;Binaries for programs local to the site. For example, a simple script to run &lt;em&gt;dropbox&lt;/em&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/usr/local/sbin&lt;/td&gt;
      &lt;td&gt;Locally installed programs for system administration. For example, a simple script to run &lt;em&gt;sslocal&lt;/em&gt; which needs root privilege.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;/opt[/bin]&lt;/td&gt;
      &lt;td&gt;This  directory  should  contain  add-on  packages  that contain static files. Reserved for the installation of add-on application software packages. A package to be installed in /opt must locate its static files in a separate /opt/package or /opt/provider directory tree, where &lt;em&gt;package&lt;/em&gt; is a name that describes the software package and &lt;em&gt;provider&lt;/em&gt; is the provider&apos;s LANANA registered name.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;~/bin&lt;/td&gt;
      &lt;td&gt;This is for user-owned private binaries. Can be appended to your $PATH.&lt;/td&gt;
  &amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;

1. You will see that files and directories that are admin only are gathered in the same directory: the `s` in /sbin and /usr/sbin and /usr/local/sbin stands for system. A normal user can not even start programs that are in there. Files a normal user can start are in /bin, /usr/bin, /usr/local/bin based on where it most logically should reside. But if they are admin only they should go to the `s` version of that directory. There is a famous utility called fuser. You can kill processes with it. If a normal user could use this (s)he would be able to kill your session.
2. The same goes for /home: /home/user1 is property of user1. /home/user2 is property of user2. user2 has no business doing stuff in user1&apos;s home (and the other way around is also true: user1 has no business doing stuff in user2&apos;s home). If all the files would be in /home with no username underneath it you would have to give permissions to every file and asses if someone is allowed to write/remove those files. A nightmare if you have tens of users.
3. Addition regarding libraries.

    /lib/, /usr/lib/, and /usr/local/lib/ are the original locations, from before multilib systems existed and the exist to prevent breaking things. /usr/lib32, /usr/lib/64, /usr/local/lib32/, /usr/local/lib64/ are 32-/64-bit multilib inventions.
4. If I&apos;m writing my own scripts, where should I add these?

    None of the above. Please use /usr/local/bin or /usr/local/sbin for system-wide (mulitple users) available scripts. The local path means it&apos;s not managed by the system packages (this is an error for Debian/Ubuntu packages). For private-owned scripts, use ~/bin in home directory.

    Always keep **multi-user** nature of Linux in mind.

Refer to [2] and [3].

[1]:http://www.linuxfoundation.org/collaborate/workgroups/lsb/fhs-30
[2]:http://askubuntu.com/a/308048
[3]:http://askubuntu.com/a/138551
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
</content>
 </entry>
 
 <entry>
   <title>Reverse proxy and forward proxy</title>
   <link href="/2015/06/03/reverse-proxy/"/>
   <updated>2015-06-03T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/06/03/reverse-proxy</id>
   <content type="html">&lt;p&gt;一般实现代理技术的方式就是在服务器上安装代理服务软件，让其成为一个代理服务器，从而实现代理技术。常用的代理技术分为正向代理、反向代理和透明代理。本文就是针对这三种代理来讲解一些基本原理和具体的适用范围，便于大家更深入理解代理服务技术。&lt;/p&gt;

&lt;h1 id=&quot;正向代理forward-proxy&quot;&gt;正向代理(Forward Proxy)&lt;/h1&gt;
&lt;p&gt;一般情况下，如果没有特别说明，代理技术默认说的是正向代理技术。关于正向代理的概念如下：&lt;/p&gt;

&lt;p&gt;正向代理(forward)是一个位于客户端【用户A】和原始服务器(origin server)【服务器B】之间的服务器【代理服务器Z】，为了从原始服务器取得内容，用户A向代理服务器Z发送一个请求并指定目标(服务器B)，然后代理服务器Z向服务器B转交请求并将获得的内容返回给客户端。&lt;strong&gt;客户端必须要进行一些特别的设置才能使用正向代理&lt;/strong&gt;。如下图所示：&lt;img src=&quot;/assets/06031.jpg&quot; alt=&quot;Alt text&quot; title=&quot;Optional title&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从上面的概念中，我们看出，文中所谓的正向代理就是代理服务器替代访问方【用户A】去访问目标服务器【服务器B】这就是正向代理的意义所在。而为什么要用代理服务器去代替访问方【用户A】去访问服务器B呢？&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A无法直接访问服务器B，譬如被拦截了，gfw。&lt;/li&gt;
  &lt;li&gt;加速。A通过代理访问B，速度更快。&lt;/li&gt;
  &lt;li&gt;cache作用。代理服务器可能已经缓存了内容。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;其实翻墙的大部分内容就涉及到正向代理技术。&lt;/p&gt;

&lt;p&gt;我们总结一下 正向代理是一个位于客户端和原始服务器(origin server)之间的服务器，为了从原始服务器取得内容，客户端向代理发送一个请求并指定目标(原始服务器)，然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须设置正向代理服务器，当然前提是要知道正向代理服务器的IP地址，还有代理程序的端口。&lt;strong&gt;正向代理是从客户端的角度来分析问题的，这正是”正向“的本义&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;#反向代理（reverse proxy）
反向代理正好与正向代理相反，对于客户端而言代理服务器就像是原始服务器，并且&lt;strong&gt;客户端不需要进行任何特别的设置&lt;/strong&gt;。客户端向反向代理的命名空间(name-space)中的内容发送普通请求，接着反向代理将判断向何处(原始服务器)转交请求，并将获得的内容返回给客户端。&lt;strong&gt;反向代理是从服务器端来分析问题的，这正是”反向“的本义&lt;/strong&gt;。反向代理的作用如下：&lt;/p&gt;

&lt;p&gt;###保护和隐藏原始资源服务器B
&lt;img src=&quot;/assets/06032.jpg&quot; alt=&quot;Alt text&quot; title=&quot;Optional title&quot; /&gt;&lt;/p&gt;

&lt;p&gt;用户A始终认为它访问的是原始服务器B而不是代理服务器Z，但实用际上反向代理服务器接受用户A的应答，从原始资源服务器B中取得用户A的需求资源，然后发送给用户A。由于防火墙的作用，只允许代理服务器Z访问原始资源服务器B。尽管在这个虚拟的环境下，防火墙和反向代理的共同作用保护了原始资源服务器B，但用户A并不知情，A以为自己把请求发送给了B，其实请求被&lt;strong&gt;服务器端技术默默地&lt;/strong&gt;发给了Z。&lt;/p&gt;

&lt;p&gt;###负载均衡 （CDN）
&lt;img src=&quot;/assets/06033.jpg&quot; alt=&quot;Alt text&quot; title=&quot;Optional title&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当反向代理服务器不止一个的时候，我们甚至可以把它们做成集群，当更多的用户访问资源服务器B的时候，让不同的代理服务器Z（x）去应答不同的用户，然后发送不同用户需要的资源。
当然反向代理服务器像正向代理服务器一样拥有CACHE的作用，它可以缓存原始资源服务器B的资源，而不是每次都要向原始资源服务器B请求数据，特别是一些静态的数据，比如图片和文件，如果这些反向代理服务器能够做到和用户X来自同一个网络，那么用户X访问反向代理服务器X，就会得到很高质量的速度。这正是CDN技术的核心，我们并不是讲解CDN，所以去掉了CDN最关键的核心技术智能DNS，只是展示CDN技术实际上利用的正是反向代理原理这块。如下图:&lt;img src=&quot;/assets/06034.jpg&quot; alt=&quot;Alt text&quot; title=&quot;Optional title&quot; /&gt;&lt;/p&gt;

&lt;p&gt;反向代理结论与正向代理正好相反，对于客户端而言它就像是原始服务器，并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求，接着反向代理将判断向何处(原始服务器)转交请求，并将获得的内容返回给客户端，就像这些内容原本就是它自己的一样。
基本上，网上做正反向代理的程序很多，能做正向代理的软件大部分也可以做反向代理。开源软件中最流行的就是squid，既可以做正向代理，也有很多人用来做反向代理的前端服务器。另外MS ISA也可以用来在WINDOWS平台下做正向代理。反向代理中最主要的实践就是WEB服务，近些年来最火的就是Nginx了。网上有人说NGINX不能做正向代理，其实是不对的。NGINX也可以做正向代理，不过用的人比较少了。&lt;/p&gt;

&lt;h1 id=&quot;透明代理&quot;&gt;透明代理&lt;/h1&gt;
&lt;p&gt;如果把正向代理、反向代理和透明代理按照人类血缘关系来划分的话。那么正向代理和透明代理是很明显堂亲关系，而正向代理和反向代理就是表亲关系了。透明代理的意思是客户端根本不需要知道有代理服务器的存在，它改编你的request fields（报文），并会传送真实IP。注意，加密的透明代理则是属于匿名代理，意思是不用设置使用代理了。透明代理实践的例子就是时下很多公司使用的行为管理软件。如下图：&lt;img src=&quot;/assets/06035.jpg&quot; alt=&quot;Alt text&quot; title=&quot;Optional title&quot; /&gt;&lt;/p&gt;

&lt;p&gt;用户A和用户B并不知道行为管理设备充当透明代理行为，当用户A或用户B向服务器A或服务器B提交请求的时候，透明代理设备根据自身策略拦截并修改用户A或B的报文，并作为实际的请求方，向服务器A或B发送请求，当接收信息回传，透明代理再根据自身的设置把允许的报文发回至用户A或B，如上图，如果透明代理设置不允许访问服务器B，那么用户A或者用户B就不会得到服务器B的数据。&lt;/p&gt;

&lt;p&gt;#代理与NAT
代理与NAT可以实现类似的功能，即隐藏地址。但它们是有本质区别的。代理是应用层的，基于的是请求转发；而NAT是IP层的，基于的是IP包转发效率要高一些。NAT的本意也想对所有的协议进行透明转换，但是NAT无法对某些数据包中的IP地址转换；部分通过代理（应用网关）能解决，但部分应用根本无法通过NAT。NAT使每一台机器对应一个相应的“假”地址，但代理服务器把所有内部网络的机器全部映射成自己的地址。而且代理服务器打破了客户机与外部服务器之间点对点连接的这种模式。这也是代理服务器与NAT最大的不同。同时也是代理服务器发展的最大障碍。因为点对点连接是Internet上提供某些服务的基础，打破了这种连接，也就无法实现这些服务，透明代理也有一样的问题。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>stardict</title>
   <link href="/2015/05/31/stardict/"/>
   <updated>2015-05-31T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/31/stardict</id>
   <content type="html">&lt;p&gt;A Linux dictionary which I think is the best. Easy configuration, and support customized dictionary.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Refer to &lt;a href=&quot;https://code.google.com/p/stardict-3/&quot;&gt;stardict-3&lt;/a&gt; and &lt;a href=&quot;http://www.huzheng.org/stardict/&quot;&gt;www.huzheng.org/stardict&lt;/a&gt;, and get an overview of the package.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Installation&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -av app-text/stardict&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;When finished installtion, it might remind:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;* Note: festival text to speech (TTS) plugin is not built. To use festival
* TTS plugin, please, emerge festival and enable &quot;Use TTS program.&quot; at:
* &quot;Preferences -&amp;gt; Dictionary -&amp;gt; Sound&quot; and fill in &quot;Commandline&quot; with:
* &quot;echo %s | festival --tts&quot;
* 
* You will now need to install stardict dictionary files. If
* you have not, execute the below to get a list of dictionaries:
* 
*   emerge -s stardict-
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Overlook this information. Since we will install real people sound. Don&apos;t need the TTL simulation one.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;stardict&lt;/em&gt; depends on &lt;em&gt;gnome-doc-utils&lt;/em&gt; package and might fail with error:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;xsltApplyStylesheet: saving to C/db-xref.xsldoc may not be possible&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;This error might be solved by:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;MAKEOPTS=&quot;-j1&quot; emerge -avt app-text/stardict;&lt;/li&gt;
      &lt;li&gt;Run &lt;em&gt;python-updater&lt;/em&gt; before emerge.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;By default, the installer does not include any dictionaries for copyright issue. So we need to install dictionaries and real people sound.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://sites.google.com/site/gtonguedict/home/stardict-dictionaries&quot;&gt;Dicts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;For each dictionary:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;filename &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; /path/to/stardic&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.zip&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;unzip &lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /media/Misc/Dicts/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;filename &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; /path/to/stardic&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.bz2&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar &lt;/span&gt;vxjpf &lt;span class=&quot;nv&quot;&gt;$filename&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; /media/Misc/Dicts/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ln -sv /media/Misc/Dicts /usr/share/stardict/dic/myDicts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The dictionaries and real sound destination could also be &lt;em&gt;~/.local/share&lt;/em&gt;. More flexibly, extract the dcits and sound to Windows partition and create symlinks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Real people sound:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;You are recommended to use &lt;a href=&quot;http://www.verycd.com/topics/133276/&quot;&gt;142000个单词语音库&lt;/a&gt;.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Stardict only uses WAV sound. For MP3, we should convert to MP3 first.&lt;/p&gt;

    &lt;p&gt;If &lt;em&gt;pronounce&lt;/em&gt; USE is enabled, &lt;em&gt;WyabdcRealPeopleTTS&lt;/em&gt; will be installed automatically. The &lt;em&gt;OtdRealPeopleTTS&lt;/em&gt; (MP3) sound must be converted to WAV by script included, which finally occupies around 3GiB space.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# tar xjvf WyabdcRealPeopleTTS.tar.bz2 -C /media/Misc/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If use 142000 sound, configure StartDict to find it. Specially, Stardict find WAV files in 2nd directory layer.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;s&gt;Set the fonts to *tahoma* otherwise the sound symbols would not display correctly or naturally&lt;/s&gt;
    &lt;p&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Set &lt;em&gt;scan&lt;/em&gt;:&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/stardict-settings.png&quot; alt=&quot;Scan&quot; title=&quot;stardict scan&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;sdcv&lt;/em&gt; is the &lt;em&gt;console&lt;/em&gt; version of &lt;em&gt;stardict&lt;/em&gt;, sharing the same set of dictionaries in &lt;em&gt;/usr/share/stardict/dic&lt;/em&gt;. It&apos;s really useful when you cannot find an X environment!&lt;/p&gt;

    &lt;p&gt;You can even add &lt;em&gt;sdcv&lt;/em&gt; to Emacs.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Capital in 21st Century Pickups</title>
   <link href="/2015/05/25/notes-capital-in-21st-centuery/"/>
   <updated>2015-05-25T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/25/notes-capital-in-21st-centuery</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;In fact, nothing can be further from truth.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It&apos;s indispensable to make use of complementary sources as well.&lt;/p&gt;

&lt;p&gt;It&apos;s enlightening to …&lt;/p&gt;

&lt;p&gt;by contrast,&lt;/p&gt;

&lt;p&gt;There is very reason to believe that …&lt;/p&gt;

&lt;p&gt;fare: progress; get on 进展; 过日子: How did you fare (ie What were your experiences) while you were abroad? 你在国外时好吗（感受如何）?&lt;/p&gt;

&lt;p&gt;beneficiary: n, person who receives sth, esp one who receives money, property, etc when sb dies 受益者; 受惠者; （尤指）承受遗产者.&lt;/p&gt;

&lt;p&gt;nominal: existing, etc in name only; not real or actual 名义上的; 不实际的; 不真实的: the nominal ruler of the country 名义上的国家统治者; (of a sum of money, etc) very small, but paid because some payment is necessary （指一笔钱等）很少的, 象徵性的&lt;/p&gt;

&lt;p&gt;foregoing:  listed, mentioned, or occurring before &lt;the foregoing=&quot;&quot; statement=&quot;&quot; can=&quot;&quot; be=&quot;&quot; proven=&quot;&quot;&gt;; preceding; just mentioned 在前的; 刚提到的; 上述的: the foregoing analysis, description, discussion, etc 以上分析﹑ 描述﹑ 论述等&lt;/the&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;the foregoing: n [sing or pl v] (fml 文) what has just been mentioned 刚提及的事物: The foregoing have all been included in the proposals. 以上各点均包括在建议中.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;replete with …&lt;/p&gt;

&lt;p&gt;in the aftermath of …; its immediate aftermath&lt;/p&gt;

&lt;p&gt;touch on/upon sth mention or deal with (a subject) briefly 提及或涉及（某问题）: The matter was hardly touched on. 那件事几乎没涉及到.&lt;/p&gt;

&lt;p&gt;seethe: (of liquids) bubble and froth as if boiling （指液体）起泡, 冒泡（似沸腾）: They fell into the seething waters of the rapids. 他们跌进了翻腾的急流中.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;be seething with &amp;lt;人&amp;gt; [因生气等而] 大发雷霆[with]; [因不平、不满等而] 举国骚动,群情哗然[with]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is tempting to see/note … 迷人的,引人的,诱人的; 引人心动 [食欲] 的&lt;/p&gt;

&lt;p&gt;stun: [Tn] daze or shock (sb), eg with sth unexpected 使（某人）目瞪口呆或感到震惊: I was stunned by the news of his death. 我得知他的死讯十分震惊&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;stunning: surprising or shocking 令人惊奇的; 令人震惊的: a stunning revelation 惊人的新发现
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;far from negligible&lt;/p&gt;

&lt;p&gt;hike: n, rise in prices, costs, etc （价格﹑ 价值等的）提高, 增加: The union demands a 7% wage hike. 工会要求提高工资7%&lt;/p&gt;

&lt;p&gt;have not failed to attract attention&lt;/p&gt;

&lt;p&gt;phenomenon -&amp;gt; pl, phenomena&lt;/p&gt;

&lt;p&gt;from the turn of twentieth century until now&lt;/p&gt;

&lt;p&gt;dreadful: causing great fear or suffering; shocking 产生极大恐惧或痛苦的; 使人震惊的: a dreadful accident, disease, nightmare 可怕的事故﹑ 疾病﹑ 恶梦&lt;/p&gt;

&lt;p&gt;rentier: 靠利息、养老金、地租、股息等生活的人&lt;/p&gt;

&lt;p&gt;heady:  having a quick effect on the senses; very exciting 迅速作用於感官的; 兴奋的: a heady perfume 气味扑鼻的香水；(of a person) excited and acting rashly （指人）激动得忘乎所以的: be heady with success 因成功而得意忘形&lt;/p&gt;

&lt;p&gt;tax heaven 避税天堂&lt;/p&gt;

&lt;p&gt;euphoria:[U] intense feeling of happiness and pleasant excitement 愉快和兴奋的感觉: She was still in a state of euphoria hours after her victory. 她获胜後几小时仍喜气洋洋&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;stock market euphoria
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;reach unprecedented height/level/degree&lt;/p&gt;

&lt;p&gt;incessant: adj not stopping; continual 不停的; 连续的; 不断的: a week of almost incessant rain 雨差不多没有停过的一个星期 * an incessant stream of visitors 络绎不绝的参观人流&lt;/p&gt;

&lt;p&gt;remunerate: [Tn, Tn.pr] ~ sb (for sth) (fml 文) pay or reward sb for work or services 酬报某人（为其工作或服务）&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;remuneration:  [U] (fml or rhet 文或修辞) payment; reward 酬金; 报酬
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;oscillate: ~ (between sth and sth) (fml fig 文, 比喻) keep moving backwards and forwards between extremes of feeling, behaviour, opinion, etc; waver （感情﹑ 行为﹑ 想法等）波动, 动摇, 犹豫: He oscillates between political extremes. 他的政治观点在两个极端之间摇摆不定；[I, Tn] (cause sth to) move repeatedly and regularly from one position to another and back again （使某物）摆动: A pendulum oscillates. 摆锤能摆动&lt;/p&gt;

&lt;p&gt;vacillate:  [I, Ipr] ~ (between sth and sth) (fml usu derog 文, 通常作贬义) keep changing one&apos;s mind; move backwards and forwards between two emotions （思想）动摇不定; 犹豫; （在两种情绪之间）变化不定: She vacillated between hope and fear.她时而抱有希望, 时而心存恐惧&lt;/p&gt;

&lt;p&gt;plummet：[I, Ipr, Ip] fall steeply or rapidly 大坡度或快速落下: House prices have plummeted in this area. 此地房价大跌. * Pieces of rock plummeted down the mountainside to the ground below. 岩石一块块顺着山的陡坡滚落到地面.&lt;/p&gt;

&lt;p&gt;scrupulous: ~ (in sth/doing sth) careful not to do wrong; absolutely honest 审慎的; 极诚实的: scrupulous in all her business dealings （她）对所有交易都十分老实&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;unsrupulous: without moral principles 无道德原则的; 不讲道德的: unscrupulousmethods, behaviour 不道德的方法﹑ 行为
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;incontestable: adj that cannot be disputed or disagreed with 无可争辩的; 不能不同意的: an incontestable fact 无可争辩的事实&lt;/p&gt;

&lt;p&gt;trade deficit; trade surplus&lt;/p&gt;

&lt;p&gt;dispel:  [Tn] drive (sth) away; cause to vanish 驱走（某事物）; 使消失: dispel sb&apos;s doubts/fears/worries 消除某人的疑虑[恐惧/烦恼] * The company is trying to dispel rumours about a take-over. 公司力图澄清有关控制权转移的流言&lt;/p&gt;

&lt;p&gt;temporal: of worldly affairs, ie not spiritual; secular 世俗的（即非宗教的）; 现世的；物质世界的或与之有关的；世俗的 the temporal possessions of the Church教堂拥有的世俗的财产；Of, relating to, or limited by time时间的：时间的、与时间有关的或受时间限制的&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tempral evolution
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;supplant: (fml 文) take the place of (sb/sth); replace 取代（某人[某事物]）; 代替: Oil has supplanted coffee as our main export. 我们的主要出口货已由原来的咖啡改为石油了. * The party leader has been supplanted by his rival. 那位党的领导人已被其对手取而代之. * She has been supplanted by another in his affections, ie He now loves sb else. 他爱上了另一个女人, 不再爱她了.&lt;/p&gt;

&lt;p&gt;advent: the ~ of sth/sb the approach or arrival of (an important person, event, etc) （重要人物﹑ 事件等的）来临, 到来: With the advent of the new chairman, the company began to prosper. 随着新主席的到来, 公司也开始有了起色&lt;/p&gt;

&lt;p&gt;blunt: (of a person, remark, etc) frank and straightforward; not trying to be polite or tactful （指人﹑ 言语等）坦诚的, 直率的, 不客气的, 欠圆通的: a blunt refusal 不客气的拒绝 * Let me be quite blunt (with you) your work is appalling. （对你）直说吧–你的工作太差劲.&lt;/p&gt;

&lt;p&gt;rest on: ~ on sb/sth depend or rely on sb/sth 依靠或依赖某人[某事物]; (of a look, etc) be directed steadily at sb/sth （指目光等）停留在某人[某物]上&lt;/p&gt;

&lt;p&gt;relegate:  [esp passive 尤用於被动语态: Tn, Tn.pr] ~ sb/sth (to sth) dismiss sb/sth to a lower or less important rank, task or state 使某人[某事物]降级﹑ 降职或降低地位: I have been relegated to the role of a mere assistant.&lt;/p&gt;

&lt;p&gt;meritocracy: (a) [U] system of government by people of high achievement 英才管理（制度）. (b) [CGp] such people in a society （社会的）英才, 精英, 贤能.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;meritocratic: adj
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;aristocracy: [CGp] highest social class; the nobility 贵族阶级; 贵族: members of the aristocracy 贵族成员；[C] most able or gifted members of any class （任何阶级或阶层的）最优秀的人物: an aristocracy of talent 人杰&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;aristocratic: adj 贵族的；有贵族气派的; 贵族化的; 装贵族派头的
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;leave aside the fact that …; leave aside, too, the fact that …&lt;/p&gt;

&lt;p&gt;instrumental: [pred 作表语] ~ in doing sth being the means of bringing sth about 作为促成某事物之手段; 有帮助; 起作用: Our artistic director was instrumental in persuading the orchestra to come and play for us. 我们的艺术指导大费唇舌请来管弦乐队为我们演出.&lt;/p&gt;

&lt;p&gt;peculiar: odd or strange 奇怪的; 奇异的; 罕有的: a peculiar taste, smell, noise, etc 怪异的口味﹑ 气味﹑ 噪音等；used or practised only by sb/sth 专用的; 特有的: customs peculiar to the 18th century 18世纪特有的风俗习惯&lt;/p&gt;

&lt;p&gt;envisage: v [Tn, Tf, Tw, Tg, Tsg] picture (an event, action, etc) in the mind as a future possibility; imagine 展望; 想像: Nobody can envisage the consequences of total nuclear war. 没有人能想像出全面核子战争的後果. * I can&apos;t envisage the plan(&apos;s) working. 我无法设想计划能否行得通.&lt;/p&gt;

&lt;p&gt;buy this argument&lt;/p&gt;

&lt;p&gt;Anglo Saxon model 又称“新美国模式”&lt;/p&gt;

&lt;p&gt;obscure the fact that …&lt;/p&gt;

&lt;p&gt;continental Europe 欧洲大陆，或称大陆的欧洲部分，主要排除英国&lt;/p&gt;

&lt;p&gt;stupendous: adj amazingly large, impressive, good, etc 极大的; 极感人的; 极好的: a stupendous mistake, achievement 极大的错误﹑ 成就 * The opera was quite stupendous! 这部歌剧很精彩!&lt;/p&gt;

&lt;p&gt;Denmark 丹麦&lt;/p&gt;

&lt;p&gt;Nordic countries: 北欧国家&lt;/p&gt;

&lt;p&gt;tumult: n, disturbance or confusion, esp of a large mass of people 混乱; （尤指大群人的）骚乱: The demonstration broke up in tumult. 示威集会在纷乱中解散了；disturbed or agitated state of mind; turmoil （思想上的）波动, 烦乱: Her mind was/Her thoughts were in a tumult. 她心烦意乱&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tumultuous/chaos/chaotic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;at/on sb`s heels; on the heels of sth following closely after sb/sth 紧跟在某人[某事物]後面: The thief ran off with an angry crowd at his heels. 那小偷在前面跑, 一群愤怒的人在後面紧追&lt;/p&gt;

&lt;p&gt;plunge: ~ (sth) into sth; ~ (sth) in:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(cause sth to) fall into sth suddenly and with force （使某物）突然而猛力投入﹑ 穿入﹑ 进入等: plunge (one&apos;s hand) into cold water （把手）一下子伸进冷水中 
(cause sth to) enter a specified state or condition （使某事物）进入或陷入某状态: The country (was) plunged into civil war after the death of the President. 总统死後全国陷入了内战. 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;armament: [C often pl 常作复数] weapons, esp the guns on a tank, an aircraft, etc 武器; （尤指坦克﹑ 飞机等配备的）大炮；武装力量; 军事力量&lt;/p&gt;

&lt;p&gt;inpassing: incidentally; in the course of doing something else; by the way;顺便提及&lt;/p&gt;

&lt;p&gt;lacuna: (pl. lacunae) section missing from a book, an argument, etc; gap （书籍﹑ 论据等中的）脱漏, 阙文, 缺漏, 空白: a lacuna in the manuscript 原稿中的脱漏&lt;/p&gt;

&lt;p&gt;amiss: adj, wrong(ly); inappropriate(ly) 错误; 不恰当: Something seems to be amiss can I help? 好像有点儿不对头–要我帮忙吗?&lt;/p&gt;

&lt;p&gt;nadir: (fig 比喻) lowest point; time of greatest depression, despair, etc 最低点; 最压抑﹑ 消沉等的时刻: This failure was the nadir of her career. 这次失败是她事业上的低谷.&lt;/p&gt;

&lt;p&gt;come by: obtain；acquire获得；得到 How did you come by that beautiful landscape painting？你是怎样弄到那张漂亮的风景画的？&lt;/p&gt;

&lt;p&gt;meager: Deficient in quantity, fullness, or extent; scanty 不足的，缺乏的：在数量、程度或范围上缺乏的；不足的&lt;/p&gt;

&lt;p&gt;deteriorate: ~ (into sth) become worse in quality or condition 变坏; 变质; 恶化: Leather can deteriorate in damp conditions. 皮革受潮可变质. * The discussion deteriorated into a bitter quarrel. 这场讨论演变成了激烈的争吵&lt;/p&gt;

&lt;p&gt;disaffection, alienation, estrangement 疏远,疏离,不和&lt;/p&gt;

&lt;p&gt;all the more to an even greater degree更；格外；更加；越加&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;all the more so 更加如此
all the more reason to do/for (doing) sth 更有理由。。。
He loved his wife and children，but he loved his country all the more．他爱妻子儿女，但是他更爱祖国
I know you find the subject difficult， but that is all the more reason why yod should work hard at it．我知道你感到这门学科困难，但这就是你更加应该努力钻研它的理由
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;rudiment: [C] imperfect beginning of sth that is not yet fully developed 初级形态: working on the rudiments of a new idea 研究一种新思想的萌芽；part or organ that is incompletely developed 未充分发展的部分; 发育不成熟的器官&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;rudimentary adj.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;complacent:  adj ~ (about sb/sth) (usu derog 通常作贬义) calmly satisfied with oneself, one&apos;s work, etc 自满的; 自鸣得意的: a complacent smile, manner, tone of voice 自满的微笑﹑ 姿态﹑ 声调 * We must not be complacent about our achievements; there is still a lot to be done. 我们绝不能满足於自己的成绩, 还有很多事情要做.&lt;/p&gt;

&lt;p&gt;top decile; top centile/percentile; top thousandth;&lt;/p&gt;

&lt;p&gt;illiterate: 不会读或不会写的; 不识字的；缺乏教育的; 教育程度很低的&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;illiteracy: [U] state of being illiterate 文盲; 缺乏教育; 无知
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;apartheid: 种族隔离(南非共和国之白人对黑人所采取之种族歧视政策)&lt;/p&gt;

&lt;p&gt;extravagant: (of ideas, speech or behaviour) going beyond what is reasonable, usual or necessary （指想法﹑ 言行）放肆的, 越轨的, 过度的: extravagant praise, behaviour, claims 过分的赞扬﹑ 放肆的行为﹑ 过高的要求 * pay extravagant compliments 过分夸奖；(in the habit of) using or spending too much; (of actions) showing this tendency （惯於）奢侈的, 挥霍的; （指行为）放纵的: an extravagant man 挥霍无度的人&lt;/p&gt;

&lt;p&gt;compensation: (美)报酬,薪水,工资,俸给 (salary)；补偿,赔偿,弥补,偿还,抵偿&lt;/p&gt;

&lt;p&gt;till: (银行、商店等的) 放现款用的抽屉; 放贵重物品用的抽屉 have one&apos;s fingers/hands in the till 从自己的工作部门偷钱，监守自盗&lt;/p&gt;

&lt;p&gt;apt: suitable; appropriate 适当的; 恰当的: an apt quotation/metaphor 恰当的引语/比喻&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[pred 作表语] ~ to do sth likely or having a tendency to do sth 易於做某事物; 有做某事物的倾向: apt to be forgetful, careless, quick-tempered, etc 健忘﹑ 总是粗心大意﹑ 动不动就发脾气 * My pen is rather apt to leak. 我的钢笔爱漏墨水.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;[not X] any more than [Y]：Y和X一样&lt;strong&gt;不&lt;/strong&gt; …&lt;/p&gt;

&lt;p&gt;per se: by or of itself; intrinsically 本身; 本质上: The drug is not harmful per se, but is dangerous when taken with alcohol. 该药本身并无害处, 但与酒类同服则有危险.&lt;/p&gt;

&lt;p&gt;disparate: so different in kind or degree that they cannot be compared 迥然不同的; 无法比较的: The five experiments gave quite disparate results. 这五次试验所获得的结果迥然不同&lt;/p&gt;

&lt;p&gt;mete:  mete sth out (to sb) (fml 文) give or administer (punishment, rewards, etc) 给予, 加以（惩罚﹑ 奖励等）,分给[人],给与: The judge meted out severe penalties. 法官对犯人予以严惩. * Justice was meted out to the offenders. 犯人均已绳之以法&lt;/p&gt;

&lt;p&gt;propensity: n ~ (for/to/towards sth); ~ (for doing/to do sth) (fml 文) inclination or tendency 倾向; 习性: a propensity to exaggerate/towards exaggeration 浮夸的倾向 * a propensity for getting into debt 借债的习性.&lt;/p&gt;

&lt;p&gt;mischief:  [U] behaviour (esp of children) that is annoying or does slight damage, but is not malicious (used esp as in the expressions shown) 恶作剧, 捣蛋, 顽皮, 淘气（尤用於以下示例）: act out of mischief 调皮的举动&lt;/p&gt;

&lt;p&gt;confiscate: [Tn] take possession of (sb&apos;s property) by authority, without payment or compensation 没收（某人的财产）; 充公: The headmaster confiscated Tommy&apos;s pea-shooter. 校长没收了汤米的射豆枪. * If you are caught smuggling goods into the country, they will probably be confiscated. 假若查出你向该国走私货物, 你的货物准得没收.&lt;/p&gt;

&lt;p&gt;levy:  [Tn, Tn.pr] ~ sth (on sb) collect (a payment, etc) by authority or force; impose sth 徵收, 徵集（款额等）; 强加某事物: a departure tax levied on all travellers 向所有旅客徵收的离境税&lt;/p&gt;

&lt;p&gt;windfall: an unexpected, unearned, or sudden gain or advantage 意外的收获&lt;/p&gt;

&lt;p&gt;think tank: 智库，智囊团 A group or an institution organized for intensive research and solving of problems, especially in the areas of technology, social or political strategy, or armament. 智囊：尤指为集中研究并解决在技术、社会或政策及军事领域中的问题而组织起来的群体或机构&lt;/p&gt;

&lt;p&gt;worrisome: causing worry; troublesome 令人忧虑的; 令人烦恼的&lt;/p&gt;

&lt;p&gt;The top decile of the wealth hierarchy own a clear majority of what there is to own.&lt;/p&gt;

&lt;p&gt;candid: adj not hiding one&apos;s thoughts; frank and honest 率直的; 坦白而诚实的: a candid opinion, statement, person 直言﹑ 直说﹑ 直性人 * Let me be quite candid with you: your work is not good enough. 不瞒你说, 你的工作不怎麽好&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;to be candid,
candidly,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;probate: [U] official process of proving that a will is correct 遗嘱检验; 遗嘱认证: apply for/take out probate 申请检验遗嘱 * grant probate 通过对遗嘱的认证；[C] copy of a will with an official certificate that it is correct 经认证的遗嘱&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[attrib 作定语] a probate court 遗嘱检验法庭
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;observatory: A structure overlooking an extensive view 观察台，了望台，望楼：俯瞰广阔景象的建筑；A building, a place, or an institution designed and equipped for making observations of astronomical, meteorological, or other natural phenomena 观测所，气象台，天文台：一座建筑或一个机构，用以观测天文的、气象学的或其它自然现象&lt;/p&gt;

&lt;p&gt;coffer: 1 (C) (放置金钱等贵重物品的) 箱柜,银柜；2 [~s] (银行等的) 金库; 财源 (funds)；the ~s of the State 国库 ；3 (C)‘建筑’ (格子、天花板、拱门等的) 饰板,镶板,藻井&lt;/p&gt;

&lt;p&gt;regime: (a) method or system of government 统治方式或制度; 政体; 政权: a socialist, fascist, etc regime 社会主义﹑ 法西斯等制度. (b) prevailing method or system of administration (eg in a business) 盛行的管理方式或制度（如商业中的）: changes made under the present regime 现行管理方法带来的变化 * the old regime versus the new 新管理制度对旧管理制度&lt;/p&gt;

&lt;p&gt;regiment: 军队中的团； ~ of sth/sb (fig 比喻) large number of things or people 大量的物或人: a whole regiment of volunteers 大批志愿者&lt;/p&gt;

&lt;p&gt;colonel: 上校（美国陆军、空军或海军陆战队中校之上准将之下的军衔）&lt;/p&gt;

&lt;p&gt;bequest: [n]act of bequeathing 遗赠: the bequest of one&apos;s paintings to a gallery 把绘画遗赠给美术馆；thing bequeathed; legacy 遗产; 遗物: leave a bequest of 2000 each to one&apos;s grandchildren 留给孙儿每人一笔2000英镑的遗产&lt;/p&gt;

&lt;p&gt;bequeath: (fml 文) [Tn, Dn.n, Dn.pr] ~ sth (to sb) 1 arrange, by making a will, to give (property, money etc) (to sb) when one dies 将（财物等）遗赠（给某人）: He bequeathed 1000 (to charity). 他遗赠（给慈善事业）1000英镑. * She has bequeathed me her jewellery. 她把珠宝遗赠给我了&lt;/p&gt;

&lt;p&gt;cadastre:an official register of the quantity, value, and ownership of real estate used in apportioning taxes&lt;/p&gt;

&lt;p&gt;conveyance: [U] (fml 文) conveying 运送; 传送; 传达; 转让: the conveyance of goods by rail 铁路货运&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(law 律) (a) [U] conveying property 转让财产: an expert in conveyance 承办产权转让事务的专家. (b) [C] document that conveys property 产权转让证书: draw up a conveyance 拟就产权转让证书.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;draw reasonable conclusions&lt;/p&gt;

&lt;p&gt;kin: [pl v] (dated or fml 旧或文) one&apos;s family and relatives 家人和亲戚: All his kin were at the wedding. 他的家人和亲戚都参加了婚礼. * He&apos;s my kin, ie related to me. 他是我的亲戚. * We are near kin, ie closely related. 我们是近亲；&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;synonym：kindred
no kin to sb: not related to sb 与某人无亲属关系
kith and kin: 亲友（亲戚和朋友）
kinship:亲戚血缘关系
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;metamorphose: [I, Ipr, Tn, Tn.pr] ~ (sb/sth) (into sth) (fml 文) (cause sb/sth to) change in form or nature （使某人[某物]）变形, 变质: A larva metamorphoses into a chrysalis and then into a butterfly. 幼虫变为蛹, 然後再变成蝴蝶. * The magician metamorphosed the frog into a prince. 魔术师把青蛙变成了王子&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;metamorphosis/metamorphoses: change of form or nature, eg by natural growth or development 变形; 变态; 变质 the social metamorphosis that has occurred in China 中国发生的社会变化
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;rhetoric:  修辞; 修辞艺术; 修辞学: impassioned rhetoric 富有表现力的修辞&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(derog 贬) elaborate language which is intended to impress but is often insincere, meaningless or exaggerated 华丽的词藻（常含华而不实之意）; 虚夸的言辞: the empty rhetoric of politicians 政客们的花言巧语
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;reassure: ~ sb (about sth) remove sb&apos;s fears or doubts; make sb confident again 消除某人的恐惧或疑虑; 恢复某人的信心; 使某人放心；&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;reassuring: adj that reassures 使人消除恐惧或疑虑的; 使人放心的: a reassuring glance, word, pat on the back 使人恢复信心的目光﹑ 话﹑ 轻拍一下背部
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;reassuring rhetoric&lt;/p&gt;

&lt;p&gt;cohort；number of people banded together 一群人，一帮人； each of the ten units forming a legion 步兵大队（军团的十分之一）&lt;/p&gt;

&lt;p&gt;suffrage：n [U] right to vote in political elections （政治性选举的）选举权, 投票权: universal suffrage, ie the right of all adults to vote 普选权（成年人均有的投票权） * Women had to fight for their suffrage. 妇女须为享有选举权而斗争&lt;/p&gt;

&lt;p&gt;inexorable：adj continuing unstoppably; relentless 不可阻挡的; 坚持不懈的; 无情的: inexorable demands, pressures, etc 无可变更的要求﹑ 无情的压力 * the inexorable march of progress 势不可挡的进展 * the inexorable decline of wealth share&lt;/p&gt;

&lt;p&gt;procure: [Tn, Dn.n, Dn.pr] ~ sth (for sb) (fml 文) obtain sth, esp with care or effort; acquire 取得某事物（尤指费心或费力）; 获得: The book is out of print and difficult to procure. 那书已绝版, 很难弄到手； [I, Tn, Dn.pr] ~ sb (for sb) (derog 贬) find (prostitutes) for clients 为宿娼者介绍（娼妓）; 拉皮条: He was accused of procuring women for his business associates. 他被指控为其生意合伙人招妓&lt;/p&gt;

&lt;p&gt;interim：n. (idm 习语) in the interim, the time between one event, process, or period and another 在其间; 在其时；adj. serving during an intermediate interval of time 暂时的; 临时的 interim arrangements, measures, proposals, etc 临时的安排﹑ 措施﹑ 建议等&lt;/p&gt;

&lt;p&gt;heir: 继承人&lt;/p&gt;

&lt;p&gt;renounce：[Tn] agree to give up ownership or possession of (sth), esp formally 同意放弃（某事物）的所有权或占有权（尤指正式地）: renounce a claim, title, right, privilege 宣布放弃要求﹑ 头衔﹑ 权利﹑ 特权；[Tn] refuse to associate with or acknowledge (esp sth/sb with a claim to one&apos;s care, affection, etc) 拒绝与（某事物[某人]）发生联系; 与（某事物[某人]）断绝关系: renounce a friendship 绝交 * He renounced his son (as an unworthy heir). 他与儿子断绝了父子关系（认为他不配作继承人）.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;renounce inheritance
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;abject:  (of conditions) wretched; hopeless （指境况）凄惨的, 绝望的: living in abject poverty/misery 过着极穷困[悲惨]的生活&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;in abject poverty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;dun: [Tn] persistently demand payment of a debt from (sb) （不断地向某人）讨债; 催讨债款&lt;/p&gt;

&lt;p&gt;budge；(cause sth to) move slightly （使某物）稍微移动, 动一动: My car&apos;s stuck in the mud, and it won&apos;t budge/I can&apos;t budge it. 我的汽车陷入泥中, 一动也不动[我无法使它移动].&lt;/p&gt;

&lt;p&gt;agrarian: adj [usu attrib 通常作定语] (of the cultivation or ownership) of land （指耕种或所有权）土地的: agrarian laws, problems, reforms 土地法﹑ 问题﹑ 改革&lt;/p&gt;

&lt;p&gt;the Middle Ages; antiquity(usually before the Middle Ages)&lt;/p&gt;

&lt;p&gt;state of affairs: If you refer to a particular state of affairs, you mean the general situation and circumstances connected with someone or something. e.g. This state of affairs cannot continue for too long, if parliament is to recover.&lt;/p&gt;

&lt;p&gt;in the wake of: as a result of；right after；following由于；紧随&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;There were many troubles in the wake of the war．战后许多麻烦接踵而来。
There were heavy losses of property in the wake of the flood．由于洪水使得财产受到重大损失。
Traders came in the wake of the conquering armies．商人随着征服的军队而来。
The students followed in the wake of the teacher．学生们跟在老师的后面。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;for the sake of: for the purpose of; because of 为了；因为 *We must be patient for the sake of peace．为了和平，我们必须有耐心。&lt;/p&gt;

&lt;p&gt;The overall trajectory is fairly similar&lt;/p&gt;

&lt;p&gt;minuscule: adj very small; tiny 极小的; 微小的&lt;/p&gt;

&lt;p&gt;caveat: (fml 文) warning; proviso 警告; 限制性条款: I recommend the deal, but with certain caveats. 我介绍这笔交易, 但有几项要提请注意.&lt;/p&gt;

&lt;p&gt;supplement VS complement: Supplement would refer to extra/additional information &lt;strong&gt;in this context&lt;/strong&gt;对被补充对象的一种加强，两者属于同一个context. Complement refers to an item that completes or goes well &lt;strong&gt;with another item&lt;/strong&gt;，两者输入不同的context，或者说是两个不同性质的东西，但是两者可以在一起相互作用，产生的更好的结果.&lt;/p&gt;

&lt;p&gt;be accustomed to the fact that …&lt;/p&gt;

&lt;p&gt;dynamism: (in a person) quality of being dynamic （人的）精力, 活力, 干劲&lt;/p&gt;

&lt;p&gt;decry: (pt, pp decried) [Tn, Cn.n/a] ~ sb/sth (as sth) speak critically of sb/sth to make him/it seem less valuable, useful, etc; disparage sb/sth 诋毁某人[某事物]以贬低其价值: He decried her efforts (as a waste of time). 他贬低她所作的努力（认为是浪费时间）.&lt;/p&gt;

&lt;p&gt;sanctuary: 圣域,避难所&lt;/p&gt;

&lt;p&gt;ineluctable: not to be avoided, changed, or resisted : INEVITABLE 不可避免的; 难免的 &lt;an ineluctable=&quot;&quot; fate=&quot;&quot;&gt;&lt;/an&gt;&lt;/p&gt;

&lt;p&gt;ground:  [I, Ipr, Tn, Tn.pr] ~ (sth) (in/on sth) (of a ship) touch the sea bottom; cause (a ship) to do this （指船）触海底, 搁浅; 使（船）触海底﹑ 搁浅: Our ship grounded in shallow water/on a sandbank. 我们的船在浅水中[在沙滩上]搁浅&lt;/p&gt;

&lt;p&gt;ground: [C esp pl 尤作复数] ~ (for sth/doing sth/to do sth) reason(s) or justification for saying, doing or believing sth 说﹑ 做或相信某事的原因或理由: You have no grounds for complaint/for complaining. 你没有抱怨的理由. * If you continue to behave like this you will give them/provide them with grounds for dismissing you. 你照这样下去就让他们找到辞退你的理由了. * Desertion is a ground (ie legally sufficient reason) for divorce. 被配偶遗弃是离婚的充足理由. * They had no grounds to arrest him. 他们没有理由逮捕他.&lt;/p&gt;

&lt;p&gt;in a sense: in a way；in one respect在某种意义上&lt;/p&gt;

&lt;p&gt;nostalgia:  [U] sentimental longing for things that are past 对往事的怀恋; 怀旧&lt;/p&gt;

&lt;p&gt;nostalgia:  [U] sentimental longing for things that are past 对往事的怀恋; 怀旧&lt;/p&gt;

&lt;p&gt;heyday: [sing] time of greatest success, prosperity, power, etc 最成功﹑ 最繁荣﹑ 最强盛等的时期: She was a great singer in her heyday. 她在自己的黄金时代是个了不起的歌唱家. * Steam railways had their heyday in the 19th century. 19世纪是蒸汽机车的全盛时期.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;one&apos;s heyday, heyday of
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;curb: [Tn] prevent (sth) from getting out of control; restrain 防止（某事物）失控; 约束: curb one&apos;s anger, feelings, etc 抑制怒火﹑ 感情等 * curb spending, waste, etc 限制开支﹑ 浪费等. [n] strap or chain passing under a horse&apos;s jaw, used to restrain the horse 马勒, 马嚼子（横放在马嘴里的皮带或铁链, 用以驾御马匹）.&lt;/p&gt;

&lt;p&gt;supremacy: 至尊,至上,无上; 最高位&lt;/p&gt;

&lt;p&gt;controvert: [Tn] (fml 文) deny the truth of (sth); argue about 否定（某事物）; 争论; 反驳: a fact that cannot be controverted 无可置辩的事实&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;controversy: a discussion marked especially by the expression of opposing views (有关意见分歧大的问题等长期性的,尤其以文字发表的) 争论,论战,争吵
incontrovertible: adj so obvious and certain that it cannot be disputed or denied 无可辩驳的; 不容否认的: incontrovertible evidence 确凿无疑的证据
It is an incontrovertible history reality that ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;subsist:  [I, Ipr] ~ (on sth) (fml 文) (continue to) stay alive, esp with little food or money; exist （继续）存活, 活下去; （尤指藉微少的食物或金钱）维持生活; 生存: How do they manage to subsist (on such a low wage)? 他们（区区这点工资）怎样餬口? * He subsisted mainly on vegetables and fruit. 他主要依靠蔬菜和水果维持生命.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;subsistence: [U] (means of) subsisting 存活; 生存; 生计; 维生之道 * [attrib 作定语] subsistence farming, ie farming that produces only enough crops for the farmer and his family to live on, leaving no surplus which could besold 自给农业（收成仅供自家食用, 无剩余出售者） * a subsistence wage, ie one that is only just enough to enable a worker to live 勉强餬口的工资
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;projection: [C] estimate of future situations or trends, etc based on a study of present ones 对未来形势的估计; 预测; 推断: sales projections for the next financial year 对下一财政年度销售情况的预测.&lt;/p&gt;

&lt;p&gt;foreordain: [usu passive 通常用於被动语态: Tn, Tf] (fml 文) (of God or fate) arrange or determine (sth) before it actually happens （指上帝或命运）注定: It was foreordained that the company would suffer a spectacular collapse. 这个公司注定要彻底垮台.&lt;/p&gt;

&lt;p&gt;ordain: [Tn, Cn.n] make (sb) a priest or minister 任命（某人）为司铎﹑ 神父或牧师: He was ordained priest last year. 去年授予他司铎一职； [Tn, Tf] (fml 文) (of God, law, authority, fate, etc) order or command; decide in advance （指上帝﹑ 法律﹑ 权威﹑ 命运等）命令, 规定, 注定: Fate had ordained that he should die in poverty. 命中注定他得死於贫困&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NOTE ON USAGE 用法: When talking about giving orders, decree and dictate can be used of individuals in positions of authority. 谈到发命令, decree和dictate均可指下达者为掌权的个人. Decree usually suggests the public announcement of a decision made by a ruler or government without consulting others *decree通常指统治者或政府不与别人商议而公开宣布的决定: The dictator decreed that his birthday would be a public holiday. 该独裁者发布命令, 将其生日定为公众假期. Dictate indicates people using their power over others *dictate用以指人用权力支配他人: Her skills were in such demand that she could dictate her own salary. 她因其技术奇货可居, 故可以主宰自己的薪金待遇. Ordain and prescribe suggest a more impersonal authority such as the law. *ordain和prescribe多用以指如法律等非个人的权力. Ordain is formal and can be used of God *ordain含庄重色彩, 可用以指上帝: Is it ordained in heaven that women should work in the home? 女人就该在家里干活儿, 这是上天的旨意吗? Prescribe is used of the law *prescribe用於法律方面: Regulations prescribe certain standards for building materials. 有规章规定建筑材料的某些标准.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;net: adj, ~ (of sth) remaining when nothing more is to be taken away 净的; 纯的: a net price, ie one from which a discount has been deducted 实价 * net profit, ie one that remains when working expenses have been deducted 纯利 * net weight, ie that of the contents only, excluding the weight of the wrappings, the container, etc 净重 * What do you earn, net of tax (ie after tax has been paid)? 你完税後净得多少?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[attrib 作定语] (of an effect, etc) final, after all the major factors have been considered （指结果等）最後的, 最终的: The net result of the long police investigation is that the identity of the killer is still a complete mystery. 警方经长时间调查, 结果凶手的身分仍全然不知
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;concatenation: ~ (of sth) (fml 文) series of things or events linked together 一系列互相关联的事物: an unfortunate concatenation of mishaps 接连的不幸.&lt;/p&gt;

&lt;p&gt;dubious: [esp pred 尤作表语] ~ (about sth/doing sth) not certain and slightly suspicious about sth; doubtful 半信半疑; 可疑: I remain dubious about her motives. 我对她的动机仍存疑念.&lt;/p&gt;

&lt;p&gt;recapitulate:  (also infml 口语作 recap) v [I, Tn, Tw] state again or summarize the main points of (a discussion, etc) 重述或概括（讨论等）的要点: Let me just recapitulate (on) what we&apos;ve agreed so far. 让我仅扼要重述一下到目前为止我们已取得的一致意见.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;口语中一般用recap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;proposition: [n] ~ (that…)statement that expresses a judgement or an opinion; assertion 观点; 见解; 主张: The proposition is so clear that it needs no explanation. 观点十分明确, 无须解释；[Tn] propose sexual intercourse to (a woman), esp in a direct and offensive way 向（女方）提出性交要求（尤指直言而放肆）; 求欢: She was propositioned several times in the course of the evening. 整个晚上有人几次向她提出非分要求&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;propose
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;tautology: (a) [U] saying the same thing more than once in different ways withoutmaking one&apos;s meaning clearer or more forceful; needlessrepetition 无谓的重复; 赘述. (b) [C] instance of this 重复的话; 赘言&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tautological adj 不必要的反复使用,同字 [同义字] 之重复,重复的,赘述的,赘言的
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;jargon:  [U] (often derog 常作贬义) technical or specialized words used by a particular group of people and difficult for others to understand 术语; 行话; 切口: scientific jargon 科学术语 * She uses so much jargon I can never understand her explanations. 她用的术语太多, 我怎麽也听不懂她的讲解&lt;/p&gt;

&lt;p&gt;placate: [Tn] make (sb) less angry; soothe or pacify 安慰, 抚慰（某人）; 使（某人）平静﹑ 息怒&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;placatory: &amp;lt;言行等&amp;gt;安抚的,怀柔的,安慰的,抚慰的,和解的: placatory remarks 安抚的话
implacable: adj, incapable of being placated, that cannot be changed or satisfied 不能变动的; 无法平息或安抚的: implacable hatred, fury, opposition 无法消解的仇恨﹑ 愤怒﹑ 对立 * an implacable enemy, rival, etc 势不两立的敌人﹑ 竞争对手等
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;amass: [Tn] gather together or collect (sth), esp in large quantities （尤指大量地）积累, 积聚, 收集（某事物）: amass a fortune 积累财富 * They amassed enough evidence to convict him on six charges. 他们搜集了足够的证据, 宣判他有六条罪状&lt;/p&gt;

&lt;p&gt;confluence: (fml 文) coming together, esp of large numbers of people 汇合, 汇集（尤指大群的人）.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;confluent: adj, 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;distinct: adj easily heard, seen, felt or understood; definite 清楚的; 清晰的; 明显的; 明白的; 明确的: The footprints are quite distinct; they must be fresh. 足迹清晰易辨, 一定是不久前留下来的.&lt;/p&gt;

&lt;p&gt;distinctive: adj ~ (of sth) that distinguishes sth by making it different from others 特别的; 有特色的: a distinctive appearance, style, smell 特殊的外表﹑ 风格﹑ 气味 *&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;这个单词突出有特点，有别于其它的优点，peculiar，characteristic。
与distinct，是完全不同的意思，apparent obvious evident manifest definite。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;vertigo：[U] feeling of losing one&apos;s balance, caused esp by looking down from a great height; dizziness 眩晕; （尤指）高处俯视性眩晕; 头晕: suffer from (an attack of) vertigo 感到（一阵）眩晕&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vertiginous: adj
dizziness
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;primogeniture: [U] fact of being a first-born child 长嗣身分；(also right of primogeniture) (law 律) system of inheritance by which an eldest son receives his parents&apos; property 长子继承权&lt;/p&gt;

&lt;p&gt;diminish: &lt;a href=&quot;cause sth to&quot;&gt;I Tn&lt;/a&gt; become smaller or less; decrease 变小; 变少; 使（某事物）变小; 使（某事物）变少; 缩小; 减少; 降低: His strength has diminished over the years. 经过这许多年月, 他的体力不如从前了.&lt;/p&gt;

&lt;p&gt;entail: [Tn] make (sth) necessary; involve 使（某事物）必要; 牵涉；必然伴有,需要，使必需, 使蒙受, 使承担: This job entails a lot of hard work. 这项工作需要十分努力. * That will entail an early start tomorrow morning. 那就需要明晨很早动身；[esp passive 尤用於被动语态: Tn, Tn.pr] ~ sth (on sb) (law 律) leave (land) to a line of heirs in such a way that none of them can give it away or sell it 限定（地产）继承人: The house and estate are entailed on the eldest daughter. 这所房子和地产限定由长女继承. * He would have sold the property long ago had it not been entailed. 这些财产若非限定继承的话, 他早就卖掉了&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;entail:[n] [U] practice of entailing land （地产的）限定继承 [C] entailed property 限定继承的财产
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;misfortune: [U] bad luck 不幸; 厄运: suffer great misfortune 遭到极大不幸； [C] instance of this; unfortunate condition, accident or event 不幸事故; 灾难; 灾祸&lt;/p&gt;

&lt;p&gt;spinster: (a) (law or fml 律或文) unmarried woman 未婚女子. (b) (often derog 常作贬义) woman who remains single after the usual age for marrying 老处女&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bachelor: 单身汉
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;whim: [n] sudden desire or idea, esp an unusual or unreasonable one; caprice 一时的兴致; 突然的念头; （尤指）突发奇想, 异想天开; 心血来潮: It&apos;s only a passing whim, ie one that will soon be forgotten. 这只不过是一闪之念. * They seem ready to indulge (ie satisfy) his every whim. 他们简直惯着他随心所欲.&lt;/p&gt;

&lt;p&gt;detriment: n (idm 习语) to the detriment of sb/sth; without detriment to sb/sth harming/not harming sb/sth 对某人[某事物]有害 [无害]; 有损於[无损於]某人[某事物]: He works long hours, to the detriment of his health. 他长时间地工作, 有损健康. * This tax cannot be introduced without detriment to the economy. 这一税制一旦施行, 必然会危害国民经济.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;detrimental: adj
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Civil Code 民法&lt;/p&gt;

&lt;p&gt;equal –&amp;gt; equality: 等同性, 同等, 平等, 相等, 等式 –&amp;gt; equilibrium: A condition in which all acting influences are canceled by others, resulting in a stable, balanced, or unchanging system.See Synonyms at balance 平衡，均衡：一种所有动作的影响都互相抵消，整个系统处于平稳的、均势的、不变的状态&lt;/p&gt;

&lt;p&gt;egalitarian: [n, adj] n, adj (person) showing or holding a belief in equal rights, benefits and opportunities for everybody 平等主义的; 平等主义者: an egalitarian attitude to voting 对投票持平等主义的态度.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;inegalitarain: adj Marked by or accepting of social, economic, or political inequality. 不平等的：具有或接受社会的、经济的或政治不平等性的
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;splendor: Magnificent appearance or display; grandeur 华丽，壮丽：辉煌华丽的表面或陈设；壮观&lt;/p&gt;

&lt;p&gt;zeal:  [U] (fml 文) ~ (for sth) (usu intense) energy or enthusiasm; keenness （通常为高度的）热忱, 热情; 热心: show zeal for a cause 表现出对一事业的热忱 * work with great zeal 热情洋溢地工作 * revolutionary,religious zeal 革命的﹑ 宗教的热诚&lt;/p&gt;

&lt;p&gt;butler: [n] chief male servant of a house, usu in charge of the wine-cellar 男管家（通常负责管理酒窖）,大管家,家务中的仆役长&lt;/p&gt;

&lt;p&gt;pussy: 小猫咪; 女性的阴部;&lt;/p&gt;

&lt;p&gt;kitten: young cat 小猫.&lt;/p&gt;

&lt;p&gt;compatriot：[n] person who was born in, or is a citizen of, the same country as another; fellow-countryman 同胞; 同国人&lt;/p&gt;

&lt;p&gt;fascist: [U] extreme right-wing dictatorial political system or views, esp (Fascism) as originally seen in Italy between 1922 and 1943 法西斯主义&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fscist: [C][常 F~]法西斯主义者,法西斯党员
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;capitalize: (phr v) capitalize on sth, use sth to one&apos;s own advantage; profit from sth 利用某事物; 从某事物中获利: capitalize on the mistakes made by a rival firm 从对方公司的错误中获益&lt;/p&gt;

&lt;p&gt;hail: [Cn.n/a] ~ sb/sth as sth enthusiastically acknowledge sb/sth as sth 热情地承认某人[某事物]为…: crowds hailing him as king, as a hero 拥他为王﹑ 赞他为英雄的群众 * (fig 比喻) The book was hailed as a masterpiece/as masterly. 这本书被誉为杰作.&lt;/p&gt;

&lt;p&gt;thereabouts:  (also US thereabout) adv ((usu after or 通常用於or之後) near that number, quantity, time, etc 近於（某数目﹑ 数量﹑ 时间等）; 大约; 左右: I&apos;ll be home at 8 o&apos;clock or thereabouts. 我8点钟回家, 8点左右吧；somewhere near there 在附近的某地: The factory is in Leeds or somewhere thereabouts. 那工厂在利兹, 也许在利兹附近&lt;/p&gt;

&lt;p&gt;wary: adj (-ier, -iest) ~ (of sb/sth) looking out for possible danger or difficulty; cautious （对可能发生的危险或困难）留意的, 小心的, 警惕的: keep a wary eye on sb 密切注意某人 * She was wary of strangers. 她很警惕陌生人. * be wary of giving offence 唯恐冒犯他人&lt;/p&gt;

&lt;p&gt;poles apart/asunder: completely different相差甚远 *They were in agreement on most world issues，but they were poles apart about the war．他们对于多数世界大事意见是一致的，但对于战争的看法却截然相反。 *Their opinions are poles asunder．他们的意见截然相反。 *The two brothers are poles apart in character．这兄弟二人性格迥异。&lt;/p&gt;

&lt;p&gt;In fact, nothing can be further from truth.&lt;/p&gt;

&lt;p&gt;outset: at/from the outset (of sth) at/from the beginning (of sth) 开端; 开始: At the outset of her career she was full of optimism but not now. 她事业伊始十分乐观, 但现在已今非昔比了. * From the outset it was clear that he was guilty. 一开始就很清楚: 他有罪&lt;/p&gt;

&lt;p&gt;verge: [n] (idm 习语) on/to the verge of sth, at or close to the point where sth new begins or takes place 在某事即将发生之际; 接近出现某事物之点: on the verge of war, success, bankruptcy 在接近战争爆发﹑ 成功﹑ 破产之际 * Her misery brought her to the verge of tears. 她难过得快要哭了&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;on/to the verge of sth
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;default: [U] (esp law 尤用於法律) failure to do sth, esp to pay a debt or appear in court 不做某事; （尤指）不还债, 不出庭，不履行债务，‘法律’不出庭,不到案&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;go into default 变成不履行债务
(idm 习语) by default：because the other party, team, etc does not appear 因对方﹑ 他队等未出场: win a case/a game by default 因对方未出席[未出场]而赢得诉讼[比赛]. 
in default of sth/sb (fml 文): because or in case sth/sb is absent 因某物[某人]未在场; 在无某物[某人]时: He was acquitted in default of strong evidence of his guilt. 因无确凿证据而判他无罪. * The committee will not meet in default of a chairman. 没有主席委员会就不开会.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;on the verge of default 赖账的边缘&lt;/p&gt;

&lt;p&gt;prodigious: adj very great in size, amount or degree, so as to cause amazement or admiration; enormous （在体积﹑ 数量或程度上）大得令人惊叹; 巨大的: a prodigious achievement 巨大的成就 * It cost a prodigious amount (of money). 这用了一笔巨款&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;prodigiously: adv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;emblem: [n] object that represents sth; symbol 象徵; 标志; 标记: The dove is an emblem of peace. 鸽子是和平的象徵. * The ring was important to her as an emblem of their love. 这枚戒指是他们爱情的象徵, 对她至为重要. * The thistle is the emblem of Scotland. 蓟是苏格兰的标志.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;emblematic: adj [usu pred 通常作表语] ~ (of sth) (fml 文) serving as an emblem; symbolic 用作象徵; 作为标志
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;solidarity: [U] unity and agreement resulting from shared interests, feelings, actions, sympathies, etc 团结; 一致: national solidarity in the face of danger 危难当头举国团结一致 * `We must show solidarity with the strikers,&apos; declared the student leaders. 学生领袖声称: ‘我们要申明与罢工工人团结一致.’&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;solidarity tax: 团结税
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;concentration of wealth&lt;/p&gt;

&lt;p&gt;spearhead: 及物动词 to be the leader of (a movement, for example): 率先：做…的先锋（如运动）：&lt;/p&gt;

&lt;p&gt;discern: [Tn] see (sth) clearly (with the senses or the mind), esp with an effort 看出, 识别, 辨认（某事物）（尤指需费力）: In the gloom I could only just discern the outline of a building. 在黑暗中我只能依稀分辨出一座建筑物的轮廓来. * One can faintly discern the flavour of lemon. 可以隐约觉得有一点柠檬味. * discern sb&apos;s true intentions 弄清某人的真实意图&lt;/p&gt;

&lt;p&gt;upshot: [sing] the ~ (of sth) the final result or outcome 最後结果; 结局；结果,结局,结论: The upshot of it all was that he resigned. 结果他辞职了&lt;/p&gt;

&lt;p&gt;rejoice: [I, Ipr, It] ~ (at/over sth) (fml 文) feel or show great joy 极欢喜; 极高兴; rejoice over a victory 为胜利而欣喜 * rejoice at sb&apos;s success 为某人的成功而高兴 * I rejoice to hear that you are well again. 得知你身体康复, 甚为欣慰. * We rejoiced that the war was over. 我们为战争结束而欢欣鼓舞.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rejoice in：(joc 谑) have or glory in (a title, etc) 有（某种称号等）; 以（有某种称号等）为荣: She rejoices in the name of Cassandra Postlethwaite. 她为有卡桑德拉?波斯尔思韦特这样的名字而引以为荣.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Wine (staging) QQ</title>
   <link href="/2015/05/15/wine-qq/"/>
   <updated>2015-05-15T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/15/wine-qq</id>
   <content type="html">&lt;p&gt;You cannot get rid of QQ even under Linux system. First install wine; then QQ. But a lot of extra configuration needs tunning.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Install lastest Wine&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;#&lt;/em&gt; echo &quot;~app-emulation/wine-1.7.46 ~amd64&quot; &amp;gt; /etc/portage/package.accept_keywords/wine&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Wine has many bugs and lacks features, and as such we&apos;d better enable the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;staging&lt;/code&gt; USE flag. As &lt;a href=&quot;https://wiki.gentoo.org/wiki/Wine#Miscellaneous&quot;&gt;Gentoo Wiki&lt;/a&gt; suggests, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;staging&lt;/code&gt; flag Installs the external patchset from &lt;a href=&quot;https://wine-staging.com&quot;&gt;Wine-Staging&lt;/a&gt;. Includes many bugfixes and features, including better performance in gaming.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;#&lt;/em&gt; echo &quot;app-emulation/wine staging&quot; » /etc/portage/package.use/wine&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;#&lt;/em&gt; emerge -av app-emulation/wine&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;Actually from &lt;a href=&quot;https://wine-staging.com&quot;&gt;Wine-Staging&lt;/a&gt;, we can install multiple Wine instances in parallel, for example from overlay &lt;a href=&quot;https://github.com/NP-Hardass/wine-overlay&quot;&gt;wine-overlay&lt;/a&gt; which is binary package. So it won&apos;t take that long for emerge. For this case, I only choose the portage method instead. I don&apos;t want two Wine instances.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Wines needs abi_x86_32 support. It will reminds you update package.use for wine.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;blockquote&gt;
      &lt;p&gt;This will take around nearly 6 hours since it needs nearly 85 dependencies, we&apos;d better emerge it at night.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;http://phpcj.org/wineqq/&quot;&gt;Wine QQ @ phpcj.org&lt;/a&gt; or &lt;a href=&quot;http://allog.ml/linux/linux%E4%B8%8B%E5%AE%89%E8%A3%85qq%E7%9A%84%E5%8A%9E%E6%B3%95%EF%BC%882%EF%BC%89-2014%E5%B9%B45%E6%9C%8812%E6%9B%B4%E6%96%B0/&quot;&gt;Wine QQ @ allog.ml&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;From above two links, get &lt;a href=&quot;/assets/wineQQ7.3L.tar.xz&quot;&gt;wineQQ7.3L.tar.xz&lt;/a&gt;. Don&apos;t forget &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-C&lt;/code&gt; option.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;$&lt;/em&gt; tar xvf /path/to/wineQQ7.3L.tar.xz -C ~/&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;This command will extract three directories:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.wine
.local
.fonts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.wine&lt;/code&gt; directory is actually where Wine stores user configuration and program files. This extracted &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.wine&lt;/code&gt; is fine-tuned for the our QQ 7.3.&lt;/p&gt;

    &lt;p&gt;Though &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.local&lt;/code&gt; fonts exists in current home directory, extract command wont delete any existing files. Instead, it only add the new files to there corresponding sub-directories. Don&apos;t worry!&lt;/p&gt;

    &lt;p&gt;We don&apos;t need the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.fonts&lt;/code&gt; directory since fonts on my system is already configured pretty good.&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;$&lt;/em&gt; rm -rf ~/.fonts&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt;:&lt;/p&gt;

    &lt;p&gt;We just installed Wine, but did &lt;strong&gt;NOT&lt;/strong&gt; configure it yet. Instead, we use the fine-tuned configuration &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.wine&lt;/code&gt; from wineQQ7.3L.tar.xz.&lt;/p&gt;

    &lt;p&gt;Up to now, QQ was installed. You can check it from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Application menu -&amp;gt; Internet -&amp;gt; Wine QQ&lt;/code&gt;. &lt;strong&gt;Don&apos;t launch it at this moment&lt;/strong&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Disabling the Menubuilder &lt;strong&gt;before installing or lanunching any Wine applications&lt;/strong&gt;.&lt;/p&gt;

    &lt;p&gt;Wine will ruin your user file association. For example, on my Xfce4 and Thunar desktop, Wine sets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;notepad&lt;/code&gt; (installed along by default) as the default &lt;em&gt;plain text&lt;/em&gt; file editor. What is more, Wine adds an right-click emnu &lt;em&gt;Open with Notepad&lt;/em&gt;. Actually, the notepad of Wine looks ugly and does not support Chinese as well. So this step should be the very &lt;strong&gt;1st thing&lt;/strong&gt; after emerging to prevent Wine from adding menu entries and desktop links.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;From &lt;a href=&quot;https://wiki.gentoo.org/wiki/Wine#Disabling_the_Menubuilder&quot;&gt;Gentoo Wiki&lt;/a&gt; for per-user bash environment.&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# File: ~/.bashrc&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Prevent Wine from adding menu entries and desktop links. The &apos;d&apos; argument means &apos;disable&apos;.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;WINEDLLOVERRIDES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;winemenubuilder.exe=d&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Froom &lt;a href=&quot;http://wiki.winehq.org/FAQ?action=recall&amp;amp;rev=479#head-c847a3ded88bac0e61aae0037fa7dbd4c7ae042a&quot;&gt;Wine FAQ&lt;/a&gt;, we can achieve the same goal as in step 1. We can check the result by searching &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;winemenubuilder.exe&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.wine/user.reg&lt;/code&gt;:&lt;/p&gt;

        &lt;blockquote&gt;
          &lt;p&gt;&quot;winemenubuilder.exe&quot;=&quot;&quot;&lt;/p&gt;
        &lt;/blockquote&gt;

        &lt;p&gt;Personally, I prefer the Wine FAQ way, though I have adopted both.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;We can actually apply this setting to system-wide (i.e. for root, for multiple accounts) according to the 2nd step of &lt;a href=&quot;http://askubuntu.com/a/400430&quot;&gt;How to prevent Wine from adding file associations?&lt;/a&gt;. This will update &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.wine/system.reg&lt;/code&gt; file as well.&lt;/p&gt;

        &lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt;, we would lost changes to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/wine/wine.inf&lt;/code&gt; if Wine were updated, while the relevant update in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.wine/systemreg&lt;/code&gt; will remain untouched.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;If you have already installed Wine and run App without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Disabling the Menubuilder&lt;/code&gt; bofore, just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rm -rf ~/.wine&lt;/code&gt; and any relevant configurations under home directory as illustrated in those references.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Run QQ: &lt;em&gt;Applications Menu -&amp;gt; Internet -&amp;gt; Wine QQ&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;If this is the first time to launch Wine related application, then Wine reminds you waiting for updating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.wine&lt;/code&gt; directory.&lt;/p&gt;

    &lt;p&gt;Why? Though we use the fine-tuned configuration of Wine QQ. But Wine was just installed and does not know anything about it. It carry on its own initialization. But don&apos;t worry, this initilization process will keep the previously fine-tuned config items.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Continuous search for less/man command</title>
   <link href="/2015/05/14/less-man-continuous-search/"/>
   <updated>2015-05-14T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/14/less-man-continuous-search</id>
   <content type="html">&lt;p&gt;When reading &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;less&lt;/code&gt; command information, you need to search contents with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/pattern&lt;/code&gt;. If continuous search needed:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;n&lt;/strong&gt;: continuous forward search&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;N&lt;/strong&gt;: continous backward search&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>tar</title>
   <link href="/2015/05/13/tar/"/>
   <updated>2015-05-13T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/13/tar</id>
   <content type="html">&lt;p&gt;&quot;tar&quot; stands for tape archive. It is an archiving file format.&lt;/p&gt;

&lt;h1 id=&quot;list-archive&quot;&gt;List archive&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-tvf&lt;/span&gt; hongkan.tar.xz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;create-archive&quot;&gt;Create archive&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cJpvf&lt;/span&gt; hongkan.tar.xz hongkan/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;c: create tar file;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;J: compress the tar file with &lt;em&gt;xz&lt;/em&gt;;&lt;/p&gt;

    &lt;p&gt;Alternatives are: z for gzip, j for bzip2.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;p: extract information about file permissions;&lt;/li&gt;
  &lt;li&gt;v: verbosely list files processed;&lt;/li&gt;
  &lt;li&gt;f: archive  file name.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;encryptsign-archive&quot;&gt;Encrypt/sign archive&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--recipient&lt;/span&gt; you@email.com &lt;span class=&quot;nt&quot;&gt;--sign&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--encrypt&lt;/span&gt; hongkan.tar.xz
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gpg &lt;span class=&quot;nt&quot;&gt;--output&lt;/span&gt; hongkan.tar.xz &lt;span class=&quot;nt&quot;&gt;--decrypt&lt;/span&gt; hongkan.tar.xz.gpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;extract-archive&quot;&gt;Extract archive&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-tvf&lt;/span&gt; hongkan.tar.xz
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xJpvf&lt;/span&gt; hongkan.tar.xz &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;hongkan/test.md]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;update-archive&quot;&gt;Update archive&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# edit hongkan/test.md&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;unxz hongkan.tar.xz
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-vf&lt;/span&gt; hongkan.tar hongkan/test.md
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rpvf&lt;/span&gt; hongkan.tar hongkan/test.md
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;xz hongkan.tar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;r: append files to the end of an archive.&lt;/p&gt;

    &lt;p&gt;There is no real way to &lt;em&gt;replace&lt;/em&gt; an existing file with the same name. Even the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-u --update&lt;/code&gt; parameter does not help.&lt;/p&gt;

    &lt;p&gt;We must first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--delete&lt;/code&gt; and then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-r --append&lt;/code&gt; the file to archive.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Cannot update compressed archives. Decompress tar first.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Firewall</title>
   <link href="/2015/05/12/firewall/"/>
   <updated>2015-05-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/12/firewall</id>
   <content type="html">&lt;h1 id=&quot;concepts&quot;&gt;Concepts&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;The paramount is to get your own VPS (virtual private server) - a server located outside of the firewall. VPS can be bought from commercial supplier. If you possess a PC outside of the firewall, that can be treated as your own VPS. Most users don&apos;t own a physical PC outside the firewall, which is an awkward situation urging them buying VPS.&lt;/li&gt;
  &lt;li&gt;Then you can deploy VPN or Shadowsocks (ss) servers on your own VPS.&lt;/li&gt;
  &lt;li&gt;Up to now, a local VPN or ss needs installed.&lt;/li&gt;
  &lt;li&gt;After that, you can penetrate the firewall through VPN or ss.&lt;/li&gt;
  &lt;li&gt;VPN and ss are parallel services. You only need one of them unless you would like to switch between these two services for better QoS.
    &lt;ol&gt;
      &lt;li&gt;ss支持区分国内外流量，传统VPN在翻出墙外后访问国内站点会变慢.&lt;/li&gt;
      &lt;li&gt;ss use small number of memory.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Choose ss instead of VPN.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;vps&quot;&gt;VPS&lt;/h1&gt;

&lt;p&gt;There are many VPS suppliers of which I chose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bandwagonhost.com&lt;/code&gt; or the so-called &quot;搬瓦工&quot;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bandwagonhost&lt;/code&gt; is easy to manage by web portal including installing VPN or ss server, offering different kinds of pricing package specifying &lt;em&gt;RAM, DISK, BANDWIDTH etc&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;My choice is &lt;a href=&quot;https://bandwagonhost.com/cart.php?a=confproduct&amp;amp;i=1&quot;&gt;$9.99 USD annually&lt;/a&gt;. Of course, it will reminds you to register your web account before paying through paypal.&lt;/p&gt;

&lt;p&gt;Pay attention to the pricing link which is an &lt;em&gt;inviting&lt;/em&gt; link. If you buy VPS through &lt;a href=&quot;https://bandwagonhost.comm&quot;&gt;bandwagonhost.com&lt;/a&gt;, you might not locate the &lt;em&gt;$9.99 USD annually&lt;/em&gt; pricing package.&lt;/p&gt;

&lt;p&gt;You need to wait for a few minutes for VPS system initialization. The default VPS system is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CentOS6 x86&lt;/code&gt;. You can also reinstall or choose a different operating system.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://bandwagonhost.com/clientarea.php&quot;&gt;bandwagonhost&lt;/a&gt;: the web portal login. The most important page is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Services -&amp;gt; My Services&lt;/code&gt;.
    &lt;ol&gt;
      &lt;li&gt;You can also click on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KiviVM Control Panel&lt;/code&gt; to get to the 2nd step.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://kiwivm.it7.net&quot;&gt;KiviVM Control Panel&lt;/a&gt;: VPS management page. Briefly go through the management panel.
    &lt;ol&gt;
      &lt;li&gt;The first tool I avail of is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;two-factor authentication&lt;/code&gt; (iOS Google Authenticator) thus another temporary code is required for each login into KiviVM.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Since CentOS6 x86 root password is not send through email any more, generate root password through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root password modification&lt;/code&gt; on the lest panel. You can now SSH into your VPS Centos with clients like Putty, MobaXterm and even SSH command line. Attention: the default SSH port is different from normal 22. You can get the port from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Main controls&lt;/code&gt;.&lt;/p&gt;

        &lt;p&gt;Don&apos;t use the root password often (create a new user account for daily operation, see below). If you need root privilege, just generate a new one!&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KiviVM password modification&lt;/code&gt;, set password for &lt;a href=&quot;https://kiwivm.it7.net&quot;&gt;KiviVM Control Panel&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You can SSH into VPS often to do work. First SSH as root, then create a daily use user account.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; adduser username
 passwd username
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Then SSH as &lt;em&gt;username&lt;/em&gt; for daily operation.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; ssh -p xxx username@host
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;A better way of SSH, please refer to &lt;a href=&quot;/2015/05/11/openssh/&quot;&gt;OpenSSH&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;ss-server-python-version&quot;&gt;ss server Python version&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;At the bottom of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KiviVM Control Panel&lt;/code&gt; lies &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KiviVM Extras&lt;/code&gt; from which you find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shadowsocks Server&lt;/code&gt;. What a relief! You no longer are bothered installing ss server manually. The default is Shadowsocks Python version. After installing finished, click &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Go back&lt;/code&gt;. Instructions on setting ss client for Windows system is illustrated. ss server will run automatically after the automatic installation.
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ps -ef | grep ssserver&lt;/code&gt; will print the ss server command:&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root       415     1  0 01:21 ?        00:00:00 /usr/bin/python /usr/bin/ssserver -p 443 -k PASSWORD -m aes-256-cfb --user nobody --workers 2 -d start
nobody     417   415  0 01:21 ?        00:00:02 /usr/bin/python /usr/bin/ssserver -p 443 -k PASSWORD -m aes-256-cfb --user nobody --workers 2 -d start
nobody     418   415  0 01:21 ?        00:00:02 /usr/bin/python /usr/bin/ssserver -p 443 -k PASSWORD -m aes-256-cfb --user nobody --workers 2 -d start
root       822   708  0 07:03 pts/0    00:00:00 grep ssserver	
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssserver -h&lt;/code&gt; will show help information&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d&lt;/code&gt; means run as a daemon in the background.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--workers 2&lt;/code&gt; will generate two processes belong to user &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nobody&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;This automatic method does not run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssserver&lt;/code&gt; with a configuration file, but with bare command line arguments.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;ss server was set to run at boot. Let&apos;s check:&lt;/p&gt;

        &lt;blockquote&gt;
          &lt;p&gt;[root@localhost ~]# ls /etc/rc.local -al&lt;/p&gt;

          &lt;p&gt;[root@localhost ~]# cat /etc/rc.d/rc.local&lt;/p&gt;

          &lt;p&gt;/usr/bin/ssserver -p &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat /root/.kiwivm-shadowsocks-port&lt;/code&gt; -k &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat /root/.kiwivm-shadowsocks-password&lt;/code&gt; -m &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat /root/.kiwivm-shadowsocks-encryption&lt;/code&gt; –user nobody –workers 2 -d start&lt;/p&gt;
        &lt;/blockquote&gt;

        &lt;p&gt;Pay attention to the command line arguments are stored in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/root/.kiwivm-shadowsocks-*&lt;/code&gt; files.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Add option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--forbidden-ip 127.0.0.1,::1&lt;/code&gt; to the &lt;em&gt;/etc/rc.d/rc.local&lt;/em&gt; file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssserver&lt;/code&gt; command for security reason.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Of course, you can also install ss server manually. Among the others, there mainly four versions of ss server: Python version, C libev version, Go version, and C++ with Qt version. Take the Python version as an example:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;yum install python-setuptools &amp;amp;&amp;amp; easy_install pip
pip install shadowsocks
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/bin/python /usr/bin/ssserver -p 443 -k PASSWORD -m aes-256-cfb --user nobody --workers 2 -d start&lt;/code&gt; as step 1.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssserver&lt;/code&gt; can also run with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-c&lt;/code&gt; parameter to specify a configuration file rather than command parameters.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssserver -c /path/to/shadowsocks.json -d start&lt;/code&gt; for example.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;A simple configuration file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/shadowsocks.json&lt;/code&gt;:&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
“server”:”0.0.0.0″,
“local_address”: “127.0.0.1”,
“local_port”:1080,
“server_port”: 8388,
“password”: “password”,
“timeout”:60,
“method”:”aes-256-cfb”,
“fast_open”: false,
“workers”: 2
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;a href=&quot;https://github.com/shadowsocks/shadowsocks/wiki/Configure-Multiple-Users&quot;&gt;multiple users&lt;/a&gt;:&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{
“server”:”0.0.0.0″,
“local_address”: “127.0.0.1”,
“local_port”:1080,
“port_password”:
{
 “8388”: “password8388″,
 “8398”: “password8398″,
 “8418”: “password8418″
  },
“timeout”:60,
“method”:”aes-256-cfb”,
“fast_open”: false,
“workers”: 2
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Shadowsocks server &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssserver&lt;/code&gt;并没有加入到开机启动，如果需要则要创建一个启动脚本，使其开机启动。&lt;/li&gt;
  &lt;li&gt;Refer to &lt;a href=&quot;https://pypi.python.org/pypi/shadowsocks&quot;&gt;shadowsocks 2.6.8&lt;/a&gt;; &lt;a href=&quot;http://www.vtestvps.tk/?p=18&quot;&gt;VPS之自建shadowsocks服务器（Centos及Ubuntu方法）&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;特别要注意：CentOS 6的&lt;em&gt;/etc/rc.local&lt;/em&gt;里的命令必须要提供全路径，仅仅提供命令名重启时不运行。如要用&lt;em&gt;/usr/bin/ssserver&lt;/em&gt;，而不是&lt;em&gt;ssserver&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;ss-client&quot;&gt;ss client&lt;/h2&gt;

&lt;p&gt;###Windows&lt;/p&gt;

&lt;p&gt;There are many clients available, my current windows 8.1 client is &lt;a href=&quot;https://github.com/shadowsocks/shadowsocks-csharp&quot;&gt;shadowsocks-csharp&lt;/a&gt;. Fill in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encryption method&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server port&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;password&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proxy port&lt;/code&gt; for client. The default proxy mode is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PAC&lt;/code&gt; (Proxy auto-config) not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Global&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;###Linux&lt;/p&gt;

&lt;p&gt;Basically, different shadowsocks on Linux system share serve and client - YES, the same package. For example, my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;banwagonhost&lt;/code&gt; uses Python shadowsocks, while Gentoo uses the same package. After installation, the package will install both server side and client side. Usually server side command is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssserver&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ss-server&lt;/code&gt;, while client side command is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sslocal&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ss-local&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;#&lt;/em&gt; emerge -av shadowsocks&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sslocal -h&lt;/code&gt; to show the detailed help message.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;#&lt;/em&gt; sslocal -s xx.xx.xx.xx -p yyyy -b 127.0.0.1 -l zzzz -k PASSWORD -m aes-256-cfb -d start&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If each time to input this command, then it is tedious, so need to write a script &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shadowsocks-sslocal.sh&lt;/code&gt;. If you&apos;d like, add it to boot:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/bin/bash

/usr/bin/python /usr/bin/sslocal -s xx.xx.xx.xx -p yyyy -b 127.0.0.1 -l zzzz -k PASSWORD -m aes-256-cfb --log-file /var/log/shadowsocks-ssloal.log -d start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Move this script to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/sbin/&lt;/code&gt;. Details refer to &lt;a href=&quot;http://askubuntu.com/q/308045&quot;&gt;bin sbin  difference&lt;/a&gt;. Change access mode to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;755&lt;/code&gt; and added to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root:root&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So each time, if need get out of GFW:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;#&lt;/em&gt; /usr/local/sbin/shawdowsocks-sslocal.sh&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Up to now, connected to my VPS server! But one step further - &lt;strong&gt;foxy proxy&lt;/strong&gt; for Firefox. After installing, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add New Proxy&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Add New Pattern Subscriptioin -&amp;gt; Go&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;https://autoproxy-gfwlist.googlecode.com/svn/trunk/gfwlist.txt&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Refer to this link for usage: &lt;a href=&quot;https://github.com/shadowsocks/shadowsocks-go&quot;&gt;shadowsocks-go&lt;/a&gt;. Though this is shadowsocks-go version, but the principle is the similar.&lt;/p&gt;

&lt;h3 id=&quot;pac-vs-global-on-windows&quot;&gt;PAC VS Global on WIndows&lt;/h3&gt;

&lt;p&gt;pac是只对被墙的使用ss，全局就是无论什么网站都用ss。&lt;/p&gt;

&lt;p&gt;pac可以自己修改，添加任意网站。当然也可以用网上网友维护的文件，最有名的是就是GFWlist列表。windows下右键点击ss client，出现一个菜单&quot;Update PAC from GFWlist&quot; 。&lt;/p&gt;

&lt;p&gt;说的简单点，就是一个被Q网址收集汇总，只要配对上就会走代理，没有配对上就不走代理，这样子就节省了一些流量，包括上网速度等问题。&lt;/p&gt;

&lt;p&gt;参考&lt;a href=&quot;http://shadowsocks.info/shadowsocks-pac/&quot;&gt;ShadowSocks教程:SS软件中的pac自动代理模式是什么？&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;vps-credentials&quot;&gt;VPS credentials&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://bandwagonhost.com/clientarea.php&quot;&gt;Official web portal client area&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;KiviVM Control Panel two-factor authentication:
    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;https://kiwivm.it7.net&quot;&gt;KiviVM password&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Temporary code from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Google Authenticator&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;CentOS6 x86 root password: ssh into CentOS for OS-specific management.&lt;/li&gt;
  &lt;li&gt;ss server password for ss client connectoin on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Shadowsocks Server&lt;/code&gt; of KiviVM control panel.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://shadowsocks.org&quot;&gt;shadowsocks.org&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/shadowsocks/shadowsocks&quot;&gt;shadowsocks github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://shadowsocks.blogspot.com/2015/01/shadowsocks.html&quot;&gt;shadowsocks搭建教程&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://shadowsocks.info/shadowsocks-bandwagonhost/&quot;&gt;ShadowSocks教程:Bandwagonhost搬瓦工一键安装Shadowsocks新手小白教程&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;notes&quot;&gt;Notes&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;SwichSharp is no longer needed.&lt;/li&gt;
  &lt;li&gt;If VPS CentOS restarted, then make sure to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssserver&lt;/code&gt; again as a daemon if you don&apos;t set it run on boot.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;DO NOT use OpenVPN&lt;/em&gt; on VPS. GFW can easily siniff OpenVPN traffic and block VPS IP.&lt;/li&gt;
  &lt;li&gt;ss优化&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Emerge</title>
   <link href="/2015/05/12/emerge/"/>
   <updated>2015-05-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/12/emerge</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;#&lt;/em&gt; emerge –resume&lt;/p&gt;

    &lt;p&gt;Think of a scenario when you have to reboot or shutdown while stilling emerging. You can just Ctrl+C to interrupt the emerging process. Later on when entering the system, run this command before any other emerge-related commands. This will save you a lot of time especially you have a long emerge list. For example, you are in the last one of 100 packages. This command will only continue to emerge the last package.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Verbose mode (-v)&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;--verbose [ y | n ] (-v short option)
Tell  emerge to run in verbose mode.  Currently this flag causes
emerge to print out GNU info errors, if any, and to show the USE
flags  that  will  be used for each package when pretending. The
following symbols are affixed to USE flags in order to  indicate
their status:


Symbol   Location    Meaning
──────────────────────────────────────────────────────────────

-        prefix      not enabled (either disabled or removed)
*        suffix      transition to or from the enabled state
%        suffix      newly added or removed
()       circumfix   forced, masked, or removed
{}       circumfix   state is bound to FEATURES settings
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Manual download.&lt;/p&gt;

    &lt;p&gt;Everytime emerging a package, the first thing emerge to do is downloading the package source code &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.tar.gz&lt;/code&gt;, and puting it in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/portage/distfiles/&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;If the Internet is slow or command line http/https is blocked (Dropbox due to GFW), you can follow the download links from emerge message in terminal to get a copy of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.tar.gz&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/portage/distfiles/&lt;/code&gt;, and then emerge again.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;World set&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Install a pkg&lt;/p&gt;

        &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--select=y -w&lt;/code&gt;: This is default action. Emerge a pkg and add to world file.&lt;/p&gt;

        &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--oneshot -1&lt;/code&gt;: Emerge as normal, but do not add the packages to the world  file for later updating.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Already installed&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--deselect=y&lt;/code&gt;: Remove  atoms  and/or  sets  from the world file. No installation is involved.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--noreplace&lt;/code&gt;: Skips the packages  specified  on  the  command-line  that  have already  been installed. One usage is add an installed pkg to world file.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--noreplace&lt;/code&gt; has other usage like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emerge -avtuDN --with-bdeps=y --noreplace firefox @world&lt;/code&gt;. This tells not to update firefox.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>OpenSSH</title>
   <link href="/2015/05/11/openssh/"/>
   <updated>2015-05-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/11/openssh</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#overview&quot; id=&quot;markdown-toc-overview&quot;&gt;Overview&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#goal&quot; id=&quot;markdown-toc-goal&quot;&gt;Goal&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#generate-public-key-pair&quot; id=&quot;markdown-toc-generate-public-key-pair&quot;&gt;Generate Public-key pair&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#distribute-the-public-key&quot; id=&quot;markdown-toc-distribute-the-public-key&quot;&gt;Distribute the public key&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ssh&quot; id=&quot;markdown-toc-ssh&quot;&gt;ssh&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#passwordless&quot; id=&quot;markdown-toc-passwordless&quot;&gt;Passwordless&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ssh-find-agent&quot; id=&quot;markdown-toc-ssh-find-agent&quot;&gt;ssh-find-agent&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ssh-config&quot; id=&quot;markdown-toc-ssh-config&quot;&gt;SSH config&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ssh-tunnel&quot; id=&quot;markdown-toc-ssh-tunnel&quot;&gt;SSH tunnel&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#make-it-simple&quot; id=&quot;markdown-toc-make-it-simple&quot;&gt;Make it simple&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#backup&quot; id=&quot;markdown-toc-backup&quot;&gt;Backup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#change-passphrase&quot; id=&quot;markdown-toc-change-passphrase&quot;&gt;Change passphrase&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#reference&quot; id=&quot;markdown-toc-reference&quot;&gt;Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;overview&quot;&gt;Overview&lt;/h1&gt;

&lt;p&gt;Secure Shell, or SSH, is a cryptographic (encrypted) network &lt;em&gt;protocol&lt;/em&gt; to allow remote &lt;em&gt;login&lt;/em&gt; and &lt;em&gt;other network services&lt;/em&gt; to operate securely over an unsecured network.&lt;/p&gt;

&lt;p&gt;In the old ages, &lt;em&gt;telnet&lt;/em&gt; protocol traffic is plain text subject to interception. Now services on SSH can be encrypted by different ciphers (i.e. RSA, DSA etc.). In addition to &lt;em&gt;remote login&lt;/em&gt;, other services can reside on SSH protocol like content transfer.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;protocol&lt;/em&gt; (i.e. SSH) is different from &lt;em&gt;implementation&lt;/em&gt; (OpenSSH) or &lt;em&gt;command&lt;/em&gt; (i.e. &lt;em&gt;ssh&lt;/em&gt;, &lt;em&gt;scp&lt;/em&gt; etc.). OpenSSH gives tool set like &lt;em&gt;ssh&lt;/em&gt;, &lt;em&gt;scp&lt;/em&gt;, &lt;em&gt;sftp&lt;/em&gt;, &lt;em&gt;ssh-keygen&lt;/em&gt; etc.&lt;/p&gt;

&lt;h1 id=&quot;goal&quot;&gt;Goal&lt;/h1&gt;

&lt;p&gt;In this post, I will setup remote login with Public-key infrastructure to achieve passwordless connection.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;local host&lt;/li&gt;
  &lt;li&gt;remote host&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;ssh&lt;/em&gt; from local host to remote host with key pair.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;generate-public-key-pair&quot;&gt;Generate Public-key pair&lt;/h1&gt;

&lt;p&gt;The core of Public-key infrastructure is creating personal public and private key pair. The public key literally is distributed &lt;em&gt;publicly&lt;/em&gt; over the Internet, while the private key is &lt;em&gt;privately&lt;/em&gt; kept by yourself.&lt;/p&gt;

&lt;p&gt;On local host that we connect from, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-keygen&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh-keygen &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/.ssh/id_rsa_github.pub &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh-keygen &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; ecdsa &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 384 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;zachary.hu@konghq.com (Kong Dev)&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/.ssh/id_rsa_kh

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh-keygen &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; rsa &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; 4096 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;email@example.com (openssh-rsa-4096)&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/.ssh/id_rsa
Generating public/private rsa key pair.
Enter file &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;which to save the key &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;/home/username/.ssh/id_rsa&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: 
Enter passphrase &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;empty &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;no passphrase&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: 
Enter same passphrase again: 
Your identification has been saved &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; /home/username/.ssh/id_rsa.
Your public key has been saved &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; /home/username/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:abcdedajfajqiefafanfaqrnafafaf8rqhfafdafjajfafeaqn rsa-keys
The key&lt;span class=&quot;s1&quot;&gt;&apos;s randomart image is:
+---[RSA 2048]----+
|        .+o+o.+==|
|       oE.o..q..=|
|      . o=o......|
|     + o.=o..s. .|
|    . + S . .... |
|     . + . ..q.  |
|    . . +    .   |
|   o ..+     w   |
|  .o==+ +        |
+----[SHA256]-----+
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Do NOT use &quot;ssh-dss&quot; (DSA) public key algorithm. Refer to &lt;a href=&quot;http://www.openssh.com/legacy.html&quot;&gt;openssh legacy&lt;/a&gt;. The default algorithm is &lt;em&gt;rsa&lt;/em&gt; such that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t rsa&lt;/code&gt; may be omitted..&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;~/.ssh/id_rsa&lt;/em&gt; is the private key (also termed as &lt;em&gt;identity&lt;/em&gt; in SSH); &lt;em&gt;~/.ssh/id_rsa.pub&lt;/em&gt; is the public key to be shared over the Internet.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It prompts for &lt;em&gt;passphrase&lt;/em&gt; to encrypt private key &lt;em&gt;locally&lt;/em&gt;. If someone steal the private key file, he cannot impersonate you to communicate on the Internet. You are encouraged to set a passphrase.&lt;/p&gt;

    &lt;p&gt;You can just press ENTER key to not use passphrase - empty passphrase to achieve &lt;em&gt;passwordless&lt;/em&gt;. This does make a difference when connecting to remote host. Details refer below.&lt;/p&gt;

    &lt;p&gt;It can be changed afterwards by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p -f&lt;/code&gt; argument.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;The default key size is 2048 which is subject to modernized brute force break. Use 4096!&lt;/li&gt;
  &lt;li&gt;The CLI option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-o&lt;/code&gt; is deprecated. Read &lt;a href=&quot;https://superuser.com/q/1455735/221946&quot;&gt;What does ssh-keygen &quot;-o&quot; do?&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;distribute-the-public-key&quot;&gt;Distribute the public key&lt;/h1&gt;

&lt;p&gt;Now share the public key file &lt;em&gt;~/.ssh/id_rsa.pub&lt;/em&gt; over the Internet to remote host. If we lost hte public key, we can restore it from the private key:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh-keygen &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/.ssh/id_rsa &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; ~/.ssh/id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;append&lt;/em&gt; the public key to &lt;em&gt;~/.ssh/authorized_keys&lt;/em&gt; on remote host.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;authorized_keys&lt;/em&gt; is a file that stores SSH public keys. Each time a new publick-key pair is generated, append the new public key to it. To accomplish this, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-copy-id&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh-copy-id -i ~/.ssh/id_rsa.pub -p 22 uname@192.168.0.10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, we can use:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cat ~/.ssh/id_rsa.pub | ssh -p 22 uname@192.168.0.10 &quot;mkdir -p ~/.ssh &amp;amp;&amp;amp; cat - &amp;gt;&amp;gt;  ~/.ssh/authorized_keys&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;192.168.0.10&lt;/em&gt; can also be the domain name of remote host.&lt;/li&gt;
  &lt;li&gt;Both ways achieve the same purpose: append the public key to &lt;em&gt;authorized_keys&lt;/em&gt; file. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-copy-id&lt;/code&gt; automatically creates &lt;em&gt;~/.ssh/authorized_keys&lt;/em&gt; if it does not exist.&lt;/li&gt;
  &lt;li&gt;Pay attention to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt; argument of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkdir&lt;/code&gt;: make parent directories as needed, no error if existing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No matter which command you chose, you should see something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;The authenticity of host &apos;[192.168.0.10]:22 ([192.168.0.10]:22)&apos; can&apos;t be established.
RSA key fingerprint is SHA256:afjaijfjfajeiqrityqpqvnbvlaeafjadfj.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
uname@192.168.0.10&apos;s password: 

Number of key(s) added: 1

Now try logging into the machine, with:   &quot;ssh -p &apos;22&apos; &apos;uname@192.168.0.10&apos;&quot;
and check to make sure that only the key(s) you wanted were added.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;SSH with Public-key has not been configured yet. So you are required to provide the remote host &lt;em&gt;uname&lt;/em&gt; password.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SSH into remote host to make sure &lt;em&gt;authorized_keys&lt;/em&gt; permission is &lt;em&gt;600&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;ssh-copy-id&lt;/em&gt; can handle permissions automatically while the alternative method might not.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;It is &lt;em&gt;distribute/copy&lt;/em&gt;, NOT &lt;em&gt;cut from local host&lt;/em&gt;. That means the public key should be kept locally.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ssh&quot;&gt;ssh&lt;/h1&gt;

&lt;p&gt;By default, sshd on remote server accepts both key-based or password-based connection. The key method is superior to password method.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 22 &lt;span class=&quot;nb&quot;&gt;uname&lt;/span&gt;@192.168.0.10

Enter passphrase &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;key &lt;span class=&quot;s1&quot;&gt;&apos;/home/username/.ssh/id_rsa&apos;&lt;/span&gt;: 
Last login: Thu Dec  3 07:59:14 2015 from 122.205.7.55
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From the output, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; prompts you to input &lt;em&gt;passphrase&lt;/em&gt; of public-key files. Recall that we have set a passphrase when generating public-key pair to encrypt public-key files on local host.&lt;/p&gt;

&lt;p&gt;If you leave the passphrase empty at setup, &lt;em&gt;ssh&lt;/em&gt; will login immediately without any interaction - &lt;em&gt;passwordless&lt;/em&gt; login. However, such login lose security of public-key files themselves.&lt;/p&gt;

&lt;p&gt;On &lt;a href=&quot;2020/10/12/macos.md&quot;&gt;macOS&lt;/a&gt;, the Terminal app would &lt;em&gt;set locale environment variables on startup&lt;/em&gt; when SSH to a remote server. This would &lt;a href=&quot;https://sskaje.me/2014/01/lc-ctype-issue/&quot;&gt;disrupt remote locale&lt;/a&gt;. Therefore, either disable that option in Terminal settings or customize remote server&apos;s &lt;em&gt;locale&lt;/em&gt; setting. For example &lt;a href=&quot;2017/04/05/centos/rhel.md&quot;&gt;CentOS&lt;/a&gt;, check &lt;em&gt;/etc/locale.conf&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;passwordless&quot;&gt;Passwordless&lt;/h1&gt;

&lt;p&gt;A better way on local host is to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Use passphrase to encrypt key pair.&lt;/li&gt;
  &lt;li&gt;Use &lt;em&gt;ssh-agent&lt;/em&gt; to unlock and cache private key.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The little program &lt;em&gt;ssh-agent&lt;/em&gt; does you a favor by managing your keys for you. You enter the passphrase once, and after that, &lt;em&gt;ssh-agent&lt;/em&gt; keeps your key cached in its memory and pulls it up whenever it is asked for it &lt;em&gt;during current X/shell session&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To use the agent first create one. Just enter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval $(ssh-agent -s)&lt;/code&gt; and that all. This will put you in a bash shell with two important environment variables &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AGENT_PID&lt;/code&gt; (agent process ID) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AUTH_SOCK&lt;/code&gt; (agent socket location on system) exported. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-agent -s&lt;/code&gt; alone does &lt;strong&gt;not&lt;/strong&gt; export the two variables automatically, which applies to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-agent -k&lt;/code&gt; etc. as well.&lt;/p&gt;

&lt;p&gt;Append the contents below to &lt;em&gt;~/.bashrc&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Start the ssh-agent if not already running&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; pgrep &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; ssh-agent &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;/usr/bin/gpg-agent &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After that you should add your key (file) by &lt;em&gt;ssh-add&lt;/em&gt;. Without arguments, it adds the standard &lt;em&gt;identity&lt;/em&gt; &lt;em&gt;~/.ssh/id_rsa&lt;/em&gt;, &lt;em&gt;~/.ssh/id_dsa&lt;/em&gt;, &lt;em&gt;~/.ssh/id_ecdsa&lt;/em&gt;, &lt;em&gt;~/.ssh/id_ed25519&lt;/em&gt; and &lt;em&gt;~/.ssh/identity&lt;/em&gt; (SSHv1). To add an identity deviant from standard location or name, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-add /location/of/key&lt;/code&gt;. &lt;em&gt;ssh-add&lt;/em&gt; will ask for &lt;em&gt;passphrase&lt;/em&gt;. After that the key is loaded into the key manager &lt;em&gt;ssh-agent&lt;/em&gt; for the whole X/shell session.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Check if any agents exist on system: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ps -ef | grep -i ssh-agent&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;ssh-agent&lt;/em&gt; is usually started at the beginning of the X session, or from a shell startup script like &quot;~/.bash_profile&quot;. It works by creating a unix-socket, and registering the appropriate environment variables so that all subsequent applications can take advantage of its services by connecting to that socket. Clearly, it only makes sense to start it in the parent process of an X session to use the set of decrypted private keys in all subsequent X applications.&lt;/p&gt;

    &lt;p&gt;On my Gentoo system, &quot;startx&quot; will help launch &lt;em&gt;ssh-agent&lt;/em&gt; automatically.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;printenv | grep -i ssh&lt;/code&gt;, check whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AGENT_PID&lt;/code&gt; (agent process ID) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AUTH_SOCK&lt;/code&gt; (agent socket location on system) are exported to current X/shell environment. All subsequent applications depend on these two variables to make use of &lt;em&gt;ssh agent&lt;/em&gt; on system.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Current agent&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;Agents found on system does NOT guarantee those two variables exported&lt;/strong&gt;. For example, a sever shared among multiple users has many agents running which might be created by some of the users. Now you login for an X/shell session. That very session (applications thereof) does NOT know anything about existing agents on system since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AUTH_SOCK&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AGENT_PID&lt;/code&gt; are not set to one of the agents.&lt;/p&gt;

    &lt;p&gt;The current agent means the agent to which &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AGENT_PID&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AUTH_SOCK&lt;/code&gt; are pointed. To switch to another agent, set the two variables to the new agent&apos;s process ID and socket path.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Example of adding key to agent.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh-add ~/.ssh/id_rsa
Enter passphrase for /home/username/.ssh/id_rsa: 
Identity added: /home/username/.ssh/id_rsa (/home/username/.ssh/id_rsa)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Type your passhrase. Now, you should NOT be prompted for a password whenever you use ssh, scp, or sftp etc. commands.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Limit: &lt;em&gt;ssh-add&lt;/em&gt; does NOT persist across reboot/shutdown/logout due to loss of &lt;em&gt;ssh agents&lt;/em&gt; or &lt;em&gt;the two variables&lt;/em&gt;. So usuallly the &lt;em&gt;passwordless&lt;/em&gt; login only lasts for the &lt;em&gt;current agent&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Each time of login and SSH connection, run &lt;em&gt;ssh-add&lt;/em&gt; once to achieve passwordless login. For a server, this is fine. But on personal laptop/PC that require shutdown frequently, it is tedious/annoying to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-add&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;This is a trade-off between security and utility. If you want &lt;em&gt;passwordless&lt;/em&gt; forever, resort to &lt;em&gt;keychain&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Reuse existing agents.&lt;/p&gt;

    &lt;p&gt;For example, on my Gentoo, &lt;em&gt;ssh-agent&lt;/em&gt; started with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;startx&lt;/code&gt; XFCE4 DE is attached to that specific X session (Xfce4-terminal emulator included). If I don&apos;t launch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;startx&lt;/code&gt; or switch to another virtual terminal (Ctrl+Alt+F2) and login, this login shell does not either start &lt;em&gt;ssh-agent&lt;/em&gt; or know the agent already launched!&lt;/p&gt;

    &lt;p&gt;We can launch &lt;em&gt;ssh-agent&lt;/em&gt; in shell&apos;s configuration script (&lt;em&gt;.bashrc&lt;/em&gt;, &lt;em&gt;.bash_profile&lt;/em&gt;, &lt;em&gt;.xinitrc&lt;/em&gt; etc.). Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval `ssh-agent -s` &amp;gt; /dev/null&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-add&lt;/code&gt; to &lt;em&gt;.xinitrc&lt;/em&gt; (mainly for X), &lt;em&gt;bash_profile&lt;/em&gt; (mainly for login shell and subsequent interactive shell), and &lt;em&gt;.bashrc&lt;/em&gt; (mainly for interactive shell).&lt;/p&gt;

    &lt;p&gt;At the end of &lt;em&gt;.bash_profile&lt;/em&gt;, &lt;em&gt;.bashrc&lt;/em&gt; is sourced. If you want to execute a shell script &lt;em&gt;only once&lt;/em&gt; for the whole login, add to &lt;em&gt;.bash_profile&lt;/em&gt; instead of &lt;em&gt;.bashrc&lt;/em&gt; (would be executed each time a new terminal emulator launched).&lt;/p&gt;

    &lt;p&gt;However, adding &lt;em&gt;ssh-agent&lt;/em&gt; and &lt;em&gt;ssh-add&lt;/em&gt; to shell&apos;s configuration script will always launch an new agent on every login. We only need SSH on demand! So the basic idea is to:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;let new X/shell reuse eixsting agents.&lt;/li&gt;
      &lt;li&gt;If there is not any agents, create one.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ssh-find-agent&quot;&gt;ssh-find-agent&lt;/h1&gt;

&lt;p&gt;ssh-find-agent is a tool:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;locating existing ssh compatible agent sockets (e.g., ssh-agent, gpg-agent, gnome-keyring, osx-keychain).&lt;/li&gt;
  &lt;li&gt;prompt to create one if no agents found.&lt;/li&gt;
  &lt;li&gt;optionally (invoked with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-a&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-c&lt;/code&gt;), sets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AUTH_SOCK&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH_AGENT_PID&lt;/code&gt; environment variables accordingly.
    &lt;ol&gt;
      &lt;li&gt;and set temporal ssh alias&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For lastest update, check GitHub.&lt;/p&gt;

&lt;h1 id=&quot;ssh-config&quot;&gt;SSH config&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man ssh_config&lt;/code&gt;. The client side config file &lt;em&gt;/etc/ssh/ssh_config&lt;/em&gt; or &lt;em&gt;~/.ssh/config&lt;/em&gt;. Local host - the host that connect from.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;ssh&lt;/em&gt; command supports a variety of different parameters. For example, in order to restrict malicious attempt, you are recommended to change default port number. Other parameters are remote host IP etc. difficult and tedious to remember and input.&lt;/p&gt;

    &lt;p&gt;There&apos;s a much more elegant and flexible solution - put those arguments in &lt;em&gt;~/.ssh/config&lt;/em&gt;. The configuration files contain sections separated by “Host” specifications, and that section is only applied for hosts that match one of the patterns given in the specification.&lt;/p&gt;

    &lt;p&gt;Each host section defines a &lt;em&gt;host alias&lt;/em&gt;. When connecting, just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh host-alias&lt;/code&gt;. &lt;em&gt;ssh&lt;/em&gt; will look up alias from config file and choose the first matched to connect to.&lt;/p&gt;

    &lt;p&gt;The first obtained value for each parameter is used, more host-specific declarations should be given near the beginning of the file, and general defaults at the end. Values at the beginning are superior to those afterwards. The order of privilege:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. command-line options
2. user&apos;s configuration file (~/.ssh/config)
3. system-wide configuration file (/etc/ssh/ssh_config)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Here is an example:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# ~/.ssh/config
Host vps
     HostName 192.168.0.10
     Port 1025
     User bob
     IdentityFile ~/.ssh/vps_rsa_key
Host github-project1
    User git
    HostName github.com
    IdentityFile ~/.ssh/github.project1.key
Host github-org
    User git
    HostName github.com
    IdentityFile ~/.ssh/github.org.key
Host github.com
    User git
    IdentityFile ~/.ssh/github.key
Host tunnel
    HostName database.example.com
    User coolio
    LocalForward 9906 127.0.0.1:3306
    IdentityFile ~/.ssh/coolio.example.key
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;From the example, different keys are set for different &lt;em&gt;github.com&lt;/em&gt; projects.&lt;/p&gt;

    &lt;p&gt;The &quot;LocalForward&quot; is interesting! 9906 (or 127.0.0.1:9906) is local port and xx.xx.xx.xx:3306 is a remote host port. SSH will establish a tunnel in between 127.0.0.1:9906 and xx.xx.xx.xx:3306 through the intermediate HostName. For example, the target host xx.xx.xx.xx only accepts connection to port 3306 locally. This example is special case for database operations. The target host is the same as HostName. Actually, it can even be &quot;www.youtube.com:443&quot;&lt;/p&gt;

    &lt;p&gt;To create the tunnel, just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh -qfCNT tunnel&lt;/code&gt;:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-q&lt;/code&gt; causes most warning and diagnostic messages to be suppressed.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-f&lt;/code&gt; force &lt;em&gt;ssh&lt;/em&gt; to background just before command execution but after password authentication.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-C&lt;/code&gt; compresses all data (including stdin, stdout, stderr, and data for forwarded X11, TCP and UNIX-domain connections). Compression is desirable on modem lines and other slow connections, but will only slow down things on fast networks.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt; does not execute a remote command.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-T&lt;/code&gt; disable pseudo-terminal allocation. As database does not require pseduo-terminal.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;The options are useful for &lt;em&gt;forwarding ports&lt;/em&gt; and &lt;em&gt;dynamic application-layer tunnel&lt;/em&gt; (need extra &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-D&lt;/code&gt; parameter). We cans specify these options on a per-host basis in configuration file (refer to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-o&lt;/code&gt; of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man ssh&lt;/code&gt;).&lt;/p&gt;

    &lt;p&gt;In addition to &lt;em&gt;LocalForward&lt;/em&gt;, there is also &lt;em&gt;RemoteRorward&lt;/em&gt;. No matter of &lt;em&gt;local&lt;/em&gt; or &lt;em&gt;remote&lt;/em&gt; forward, VPS should have a public IP while the &lt;em&gt;LocalForward&lt;/em&gt; or &lt;em&gt;RemoteForward&lt;/em&gt; host (NOT the vps - &lt;em&gt;uname@remote-host&lt;/em&gt;) usually don&apos;t have public IP or are blocked from each other.&lt;/p&gt;

    &lt;p&gt;For instance, two host A and C are separated by their NAT networks. Host B are on the Internet with public IP which is accessible by A and B but not the reverse! How to achieve A and C&apos;s communication by SSH? Use &lt;em&gt;remoteforward&lt;/em&gt;! A establishes remote forward to B. After that C connection to B will be forwarded to A.&lt;/p&gt;

    &lt;p&gt;Aside, there is another port forwarding - &lt;em&gt;dynamic port forwarding&lt;/em&gt; (details below).&lt;/p&gt;

    &lt;p&gt;Refer to &lt;a href=&quot;https://www.v2ex.com/t/127124&quot;&gt;SSH 隧道与端口转发（v2ex 首发）&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;scp&lt;/em&gt; can also make use of the config file.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;scp bandwagon:~/Document/file.txt &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;scp ~/Document/video.mp4 bandwagon:/Downloads
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man sshd_config&lt;/code&gt;. The server side config file &lt;em&gt;/etc/ssh/sshd_config&lt;/em&gt;. Remote host - the host that connect to.&lt;/p&gt;

    &lt;p&gt;You can disable account password login by &lt;em&gt;PasswordAuthentication no&lt;/em&gt;. Then remote host can only be accessed by public-key pair. Be careful, if you lost the key pair, you probably could no longer login.&lt;/p&gt;

    &lt;p&gt;You can also put &lt;em&gt;~/.ssh/authorized_keys&lt;/em&gt; somewhere, and set &lt;em&gt;AuthorsizedKeysFile /path/to/authorized_keys&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ssh-tunnel&quot;&gt;SSH tunnel&lt;/h1&gt;

&lt;p&gt;We can use SSH tunnel to bypass GFW.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh &lt;span class=&quot;nt&quot;&gt;-qfNT&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt; 127.0.0.1:12345 user@vps.ip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On slow network connections, try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-C&lt;/code&gt; to compress data. However, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-C&lt;/code&gt; will downgrade connection on fast network.&lt;/p&gt;

&lt;p&gt;Refer to &lt;a href=&quot;http://www.pchou.info/linux/2015/11/01/ssh-tunnel.html&quot;&gt;SSH隧道翻墙的原理和实现&lt;/a&gt; and &lt;a href=&quot;http://www.cenhq.com/2015/12/18/ssh-tunnel-over-the-wall/&quot;&gt;ssh隧道翻墙&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;make-it-simple&quot;&gt;Make it simple&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;By ssh-find-agent:
    &lt;ol&gt;
      &lt;li&gt;ssh-find-agent&lt;/li&gt;
      &lt;li&gt;ssh&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;What we have:
    &lt;ol&gt;
      &lt;li&gt;eval &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-agent -s&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;ssh-add&lt;/li&gt;
      &lt;li&gt;ssh&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;backup&quot;&gt;Backup&lt;/h1&gt;

&lt;p&gt;Different from Gnupg key&apos;s binary format, OpenSSH key (&lt;em&gt;~/.ssh/id_rsa&lt;/em&gt; and &lt;em&gt;~/.ssh/id_rsa.pub&lt;/em&gt;) is stored in &lt;em&gt;armor&lt;/em&gt; format. To backup the key, just copying the private key.&lt;/p&gt;

&lt;p&gt;Public key can be easily generated from private key by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-keygen -f ~/.ssh/id_rsa -y &amp;gt; ~/.ssh/id_rsa.pub&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;change-passphrase&quot;&gt;Change passphrase&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh-keygen &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://wsgzao.github.io/post/ssh/&quot;&gt;使用密钥登录并禁止口令登录实践&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.cyberciti.biz/faq/ssh-password-less-login-with-dsa-publickey-authentication/&quot;&gt;setup SSH with DSA public key authentication (password less login)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://mah.everybody.org/docs/ssh&quot;&gt;Using ssh-agent with ssh&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.jiangmiao.org/blog/559.html&quot;&gt;ssh无密码登入设置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys--2&quot;&gt;How To Set Up SSH Keys&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.gentoo-wiki.info/HOWTO_SSH_without_a_password&quot;&gt;how to ssh without a password&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.joncairns.com/2013/12/understanding-ssh-agent-and-ssh-add/&quot;&gt;Understanding ssh-agent and ssh-add&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wwalker/ssh-find-agent&quot;&gt;ssh-find-agent&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://nerderati.com/2011/03/17/simplify-your-life-with-an-ssh-config-file/&quot;&gt;ssh config&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.trackets.com/2014/05/17/ssh-tunnel-local-and-remote-port-forwarding-explained-with-examples.html&quot;&gt;ssh tunnel&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://vimeo.com/54505525&quot;&gt;magic of ssh&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/&quot;&gt;实战 SSH 端口转发&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>local overlay for wpa_supplicant</title>
   <link href="/2015/05/11/local-overlay/"/>
   <updated>2015-05-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/11/local-overlay</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Once for a while after an update, you system might bump into problem due to a new package version or to an unstable package. Thus the trouble-making packages should be downgraded to its old working version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recently, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant&lt;/code&gt; has upgraded from 2.3 to 2.4, resulting in unable to connecting to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HUST_WIRELESS_AUTO&lt;/code&gt;. After days of surfing on the Internet, I found the solution: downgrade &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant&lt;/code&gt; to 2.3. But before that, let&apos;s see how to position the problem. That is to say how do I get to know it is due to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant&lt;/code&gt; update causing no Wifi connection.&lt;/p&gt;

&lt;p&gt;At the very beginning, I am in a mess on the Internet without any useful information since this problem is brand new. Even Google cannot search any clues. Af very first, I thought it was due to patches to kernel. So I reinstall the system with 4.0.0 instead of 4.0.0-r3, which turned out be in vain.&lt;/p&gt;

&lt;p&gt;I searched on the Internet again for a day with nothing gain. I also read through the Gentoo &lt;a href=&quot;https://wiki.gentoo.org/wiki/Wpa_supplicant&quot;&gt;wpa_supplicant wiki&lt;/a&gt; since this package is the key of no connection to Wifi. Then I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dmesg | tail -n 35&lt;/code&gt; or the recommended debug mode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant -Dnl80211 -iwlp3s0 -C/var/run/wpa_supplicant/ -c/etc/wpa_supplicant/wpa_supplicant.conf -dd&lt;/code&gt;. Found an error message &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reason 15: 4 way handshake timeout&lt;/code&gt;, which is not useful at all when searching online.&lt;/p&gt;

&lt;p&gt;Finally, on some Internet page, I was directed to an &lt;strong&gt;important link&lt;/strong&gt;: &lt;a href=&quot;https://wireless.wiki.kernel.org/en/users/documentation/wpa_supplicant&quot;&gt;wpa_supplicant Linux documentation page&lt;/a&gt;. Great! One step closer to solution.&lt;/p&gt;

&lt;p&gt;From that link, you can find many useful information: &lt;em&gt;development branch ChangeLog&lt;/em&gt;, &lt;em&gt;stable branch ChangeLog&lt;/em&gt;, and &lt;a href=&quot;http://lists.shmoo.com/pipermail/hostap/&quot;&gt;&lt;strong&gt;New mailing list archives&lt;/strong&gt;&lt;/a&gt; where the newest package related issues usually lies. Mailing list reports immediate package discussion even before Bug report system.&lt;/p&gt;

&lt;p&gt;Following the mailing archives, I found &lt;a href=&quot;http://lists.shmoo.com/pipermail/hosfftap/2015-April/032685.html&quot;&gt;Unable to connect to WPA2-Enterprise since 2.4-r1: WPA_ALG_PMK bug?&lt;/a&gt; which unfold the mystery on Wifi problem. Everything is there! Again, I searched the subject get another link &lt;a href=&quot;https://www.marc.info/?t=143013943600001&amp;amp;r=1&amp;amp;w=4&quot;&gt;Unable to connect to WPA2-Enterprise since 2.4-r1: WPA_ALG_PMK bug?&lt;/a&gt; which is fairly concise: wpa_supplicant &amp;gt;= 2.4 encountering problems with WPA2-Enterprise networks.&lt;/p&gt;

&lt;p&gt;Through the discussion there, I found several solutions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Downgrade wpa_supplicant to 2.3 (&amp;lt;2.4) with the help of local overlay.&lt;/li&gt;
  &lt;li&gt;Ask the university to update its FreeRadius server from to 2.2.6 to 2.2.7.&lt;/li&gt;
  &lt;li&gt;Disable TLS v1.2 with phase1=&quot;tls_disable_tlsv1_2=1&quot; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/wpa_supplicant/wpa_supplicant.conf&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HUST_WIRELESS_AUTO&lt;/code&gt;. That said, this does result in older TLS version being used and that is not really a good long term
solution.&lt;/li&gt;
  &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key_mgmt_offload=0&lt;/code&gt; to the wpa_supplicant configuration file (at global level, i.e., not within a network block).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Obviously, the 3rd method simple and effective. In reality, I prefer the 3rd method.  But I would like to try the 1st instead since I want to try the process of creating a local overlay. I did not test the 4th option.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Search wpa_supplicant version information:&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emerge --search wpa_supplicant&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;But that returns only trouble versions &amp;gt;=2.4. That is to say, the old working version &amp;lt;2.4 is no longer in the official portage tree.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mask versions that does not work:&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo &quot;&amp;gt;=net-wireless/wpa\_supplicant-2.4&quot; &amp;gt; /etc/portage/package.mask/wpa_supplicant&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;From above two steps, we know there are no working versions in official portage tree. All the trouble versions in official portage are masked. How to handle this?&lt;/p&gt;

    &lt;p&gt;Local overlay! The basic idea is to create local overlay and then download the old version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ebuild&lt;/code&gt; and corresponding supporting files.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Create local overlay, refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/Overlay/Local_overlay&quot;&gt;Overlay/Local overlay&lt;/a&gt;:
    &lt;ol&gt;
      &lt;li&gt;# mkdir -p /usr/local/portage/{metadata,profiles}&lt;/li&gt;
      &lt;li&gt;# echo &apos;zhtux&apos; &amp;gt; /usr/local/portage/profiles/repo_name&lt;/li&gt;
      &lt;li&gt;# echo &apos;masters = gentoo&apos; &amp;gt; /usr/local/portage/metadata/layout.conf&lt;/li&gt;
      &lt;li&gt;# chown -R root:portage /usr/local/portage&lt;/li&gt;
      &lt;li&gt;# chmod g+s /usr/local/portage&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;# nano -w /etc/portage/repos.conf/local.conf:&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zhtux]
location = /usr/local/portage
masters = gentoo
auto-sync = no
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Adding an ebuild to the local overlay. Now we need to locate wpa_supplicant 2.3, 2.3-r1, or 2.3-r2 ebuild file and download it
    &lt;ol&gt;
      &lt;li&gt;Go through &lt;a href=&quot;https://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/net-wireless/wpa_supplicant/&quot;&gt;/net-wireless/wpa_supplicant&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;You cannot find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant-2.3*.ebuild&lt;/code&gt; since version 2.3 is out of portage tree: dead.&lt;/li&gt;
      &lt;li&gt;Click on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Show 78 dead files&lt;/code&gt; from which you will find old ebuild files: wpa_supplicant-2.3.ebuild, wpa_supplicant-2.3-r1.ebuild, and wpa_supplicant-2.3-r2.ebuild. Here I choose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant-2.3-r2.ebuild&lt;/code&gt;. Download this file from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Links to HEAD: (view) (download) (annotate)&lt;/code&gt;. Then click on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hide 78 dead files&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;# mkdir -p /usr/local/portage/net-wireless/wpa_supplicant&lt;/li&gt;
      &lt;li&gt;# cd /usr/local/portage/net-wireless/wpa_supplicant&lt;/li&gt;
      &lt;li&gt;# cp /path/to/downloaded/wpa_supplicant-2.3-r2.ebuild /usr/local/portage/net-wireless/wpa_supplicant/&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;# cp /usr/portage/net-wireless/wpa_supplicant/metadata.xml .&lt;/p&gt;

        &lt;p&gt;&lt;em&gt;metadata.xml&lt;/em&gt; is a XML file denoting package information. Usually just a few lines.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;# repoman manifest (pay attention to: the current directory) or ebuild wpa_supplicant-2.3-r2.ebuild digest&lt;/p&gt;

        &lt;p&gt;Calculate the package source (download from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GENTOO_MIRROR&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SRC_URI&lt;/code&gt;) checksum and put into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Manifest&lt;/code&gt;.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;# repoman scan -d&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;# repoman full -d -x&lt;/p&gt;

        &lt;p&gt;Check if any errors. If successfull, get a line:&lt;/p&gt;

        &lt;blockquote&gt;
          &lt;p&gt;RepoMan sez: &quot;If everyone were like you, I&apos;d be out of business!&quot;&lt;/p&gt;
        &lt;/blockquote&gt;
      &lt;/li&gt;
      &lt;li&gt;# chown -R portage:portage /usr/local/portage&lt;/li&gt;
      &lt;li&gt;# emerge -av –oneshot wpa_supplicant
        &lt;ol&gt;
          &lt;li&gt;This will not install wpa_supplicant 2.3-r2 since it complains lacking files. If you go back to step 1, you will find a folder &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/net-wireless/wpa_supplicant/files&lt;/code&gt;. Items under this directory is supporting files like patches. Supporting files are downloaded when you sync the portage. For local overly, we need to put the files manually.&lt;/li&gt;
          &lt;li&gt;On the other hand, emerge only downloads the source tarbar for wpa_supplicant-2.3-r2. It is specified in the ebuild file:&lt;/li&gt;
        &lt;/ol&gt;

        &lt;blockquote&gt;
          &lt;p&gt;# grep &quot;SRC_URI=&quot; /usr/local/portage/net-wireless/wpa_supplicant/wpa_supplicant-2.3-r2.ebuild&lt;/p&gt;
        &lt;/blockquote&gt;

        &lt;p&gt;The downloaded source file is kept under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/portage/distfiles/&lt;/code&gt;.&lt;/p&gt;
        &lt;ol&gt;
          &lt;li&gt;The 3rd emerge optiono is number one, not character L. This means for one time installation.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;# mkdir files
        &lt;ol&gt;
          &lt;li&gt;Now based the emerge error message, we go to step 1, and download the missing files.&lt;/li&gt;
          &lt;li&gt;We can also read through the ebuild files to locate what supporting files needed.&lt;/li&gt;
          &lt;li&gt;The top of the page in step 1 reminds that we can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cvs&lt;/code&gt; command to locate the files.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Each time, change the ebuild, re-run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;repoman&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;GitHub&lt;/p&gt;

    &lt;p&gt;It&apos;s useful to push local portage to Github for backup.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Reference&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;https://wireless.wiki.kernel.org/en/users/documentation/wpa_supplicant&lt;/li&gt;
  &lt;li&gt;https://www.marc.info/?t=143013943600001&amp;amp;r=1&amp;amp;w=4&lt;/li&gt;
  &lt;li&gt;http://lists.shmoo.com/pipermail/hostap/2015-April/032685.html&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;https://www.marc.info/?l=hostap&amp;amp;m=143077239911058&amp;amp;w=4&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;phase1=&quot;tls_disable_tlsv1_2=1&quot;&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;http://blog.csdn.net/zhuyingqingfen/article/details/7830624&lt;/li&gt;
  &lt;li&gt;https://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/net-wireless/wpa_supplicant/&lt;/li&gt;
  &lt;li&gt;https://wiki.gentoo.org/wiki/Overlay/Local_overlay&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>as such</title>
   <link href="/2015/05/11/as-such/"/>
   <updated>2015-05-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/11/as-such</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;as such&lt;/strong&gt; 这一短语中的 such 是代词，指代前面提到的某一名词或名词短语，关键是，“such&quot;作为代词。&lt;/p&gt;

&lt;p&gt;一、“像这样的人或事物”、“以这种名义、身份或资格”、“像这样的情况”，也可以当”因此“来翻译，therefore, so, as a result等可以替代它。Such is a pronoun that must have an identifiable antecedent. If it doesn&apos;t have one, its use is incorrect. 这里as such主要用于分句中，指代前面分句或语句中的名词、代词。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1）He is a brilliant scholar in biological engineering and he is everywhere recognized as such.     
   他是一位生物工程杰出的学者，这是世界各地都一致公认的。
2）She&apos; is a competent leader and has always been regarded as such by hercolleagues.   
   她是个很有能力的领导人, 她的同事一向都是这样认为的。
3）Man is a biological organism and as such has needs in common with all animals for food and shelter.   
   人是生物体,作为生物体人与动物一样需食物和住所。
4）So far as I am aware, she is the author of the article, but she does not desire to be known as such.    
   据我所知，她是这篇文章的作者，但她不想让人知道她是这篇文章的作者。
5）She is a kind woman and as such is known to everybody.      
   她是位好心肠的女人，这是大家知道的。
6）The film was a romance, and as such it had the usual happy ending.     
   那部影片很浪漫,作为浪漫影片,它通常都有一个愉快的结局。
7）You are new to this job, and as such, I will have to train you.  
   这份工作你是新手,我将不得不训练你。
8）I cannot accept your manuscript as such. It needs revisions.   
   你这样的手稿我不能接受，它需要修改。
9）As such, it is not completely convincing. More proofs are needed.   
   仅此还不足以令人信服, 还需要有更多的证据。
10）As such, the style of study is a question of extraordinary, indeed of primary, importance.   
   既然是这样，学风问题就是一个非常突出的问题，第一个重要的问题。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Refer to &lt;a href=&quot;http://www.law.louisville.edu/node/2554&quot;&gt;Don&apos;t misuse as such&lt;/a&gt;; &lt;a href=&quot;http://www.qiao-you.com/index.php/article/detail/uid/19868.html&quot;&gt;英语‘as such’的用法&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;二、置于名词后面，表示in the exact sense of the word，意为“就本身而论”、“… 本身”、“如词本身意思所指”。as the word is usually understood; in the strict sense of the word 按照某词通用的词义; 根据某词严格的词义。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1）Money, as such, does not bring happiness.      
   钱本身并不给人带来快乐。
2）I am not against taxes as such, but do object when taxation is justified on
   spurious or dishonest grounds.   
   我不是反对税收本身,但我确实反对莫名的或不正当的理由的税收。
3）The shop doesn&apos;t sell books as such, but it does sell magazines and
   newspapers.   
   商店不卖书,但它确实卖杂志和报纸。
4）I don’t oppose the plan as such, but I don’t thing it is proper at the
   present time.   
   我不是反对这个计划本身，我只是认为现在实施这个计划不合时宜。
5）There are no bad materials as such, but only bad articles.     
   没有不好的素材，只有不好的文章。
6）The gift as such wmay be of little worth，but it embodies her goodness.     
   这礼物本身也许没有价值, 但它包含着她的一片好意。
7）The officer of the law, as such, is entitled to respect.  
	一个执法官本身应受到人们的尊敬。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;三、有时用于否定句中表示按某词词义“算不上…”、“并不真是…”、“象样的”，同样至于名词后面，和第二条用法一致。这里只是多了一个否定not，用于强调否定句子。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1）It’s not an agreement as such, but it will have virtually the same effect as one.      
  就协议的词义而言，它算不上是协定，但实际上起到了协定的作用。
2）I can’t call my book a best seller as such, but it’s very popular.     
  我不敢说我的书是畅销书，但可以说很受欢迎。
3）The new job is not a promotion as such，but it has good prospects.    
  这份新工作算不上是晋升,但它有较好的前景。
4）The position, as such, does not appeal to him, but the salary is a lure.   
  这个位置称算不上对他有什么吸引力,但薪水倒是蛮有诱惑的。
5）He isn&apos;t American as such, but he&apos;s spent most of his life there.   
  他算不上是美国人,但他一生中大部分时间都是在美国生活的。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>wgetpaste default to gists</title>
   <link href="/2015/05/06/wgetpaste-gists/"/>
   <updated>2015-05-06T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/05/06/wgetpaste-gists</id>
   <content type="html">&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;wgetpaste&lt;/em&gt; is tool to conveniently paste your text and code snippet online around. However, it defaults to &lt;em&gt;bpaste&lt;/em&gt; which relatively weak compared to &lt;em&gt;gist&lt;/em&gt;. In this post, I will configure &lt;em&gt;wgetpaste&lt;/em&gt; to use &lt;em&gt;gist&lt;/em&gt; instead.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;$ wgetpaste -h&lt;/p&gt;

    &lt;p&gt;This command will show the basic command options.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;$ wgetpaste -S&lt;/p&gt;

    &lt;p&gt;This will list free &lt;em&gt;service&lt;/em&gt; supported by &lt;em&gt;wgetpaste&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; Services supported: (case sensitive):
    Name:        | Url:
    =============|=================
    *bpaste      | https://bpaste.net/
     ca          | http://pastebin.ca/
     codepad     | http://codepad.org/
     dpaste      | http://dpaste.com/
     lugons      | https://paste.lugons.org/
     poundpython | http://paste.pound-python.org/
     gists       | https://api.github.com/gists
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;The default service is &lt;em&gt;bpaste&lt;/em&gt; with a &lt;em&gt;*&lt;/em&gt; ahead.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Now we need to change it to &lt;em&gt;gists&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c&quot;&gt;# ect /etc/wgetpaste.d/gists.conf&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt;DEFAULT_SERVICE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;gists&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;&lt;em&gt;wgetpaste&lt;/em&gt; supports many other options, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DEFAULT_{NICK,LANGUAGE,EXPIRATION}[_${SERVICE}]&lt;/code&gt; included.&lt;/p&gt;

    &lt;p&gt;Run &lt;em&gt;wgetpaste -S&lt;/em&gt; again to verify configuration.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;$ wgetpaste ~/Documents/test-file&lt;/p&gt;

    &lt;p&gt;Up to now, &lt;em&gt;wgetpaste&lt;/em&gt; will paste text and code snippet as &lt;strong&gt;anonymous&lt;/strong&gt; &lt;a href=&quot;https://gist.github.com&quot;&gt;gist.github.com&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;anonymous gist&lt;/em&gt; cannot be searched later on.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;wgetpaste&lt;/em&gt; to GitHub &lt;em&gt;account&lt;/em&gt;.
    &lt;ol&gt;
      &lt;li&gt;Go to GitHub &lt;em&gt;settings&lt;/em&gt; and find &lt;em&gt;Personal access tokens&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Choose &lt;em&gt;Generate new token&lt;/em&gt; and set the token description to &lt;em&gt;wgetpaste&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Change token right to &lt;em&gt;gist&lt;/em&gt; only.&lt;/li&gt;
      &lt;li&gt;Edit &lt;em&gt;/etc/wgetpaste.d/gists.conf&lt;/em&gt;:&lt;/li&gt;
    &lt;/ol&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # /etc/wgetpaste.d/gists.conf
 HEADER_gists=&quot;Authorization: token 1234abc56789...&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Test again &lt;em&gt;wgetpaste ~/Documents/test-file&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Now each &lt;em&gt;wgetpaste&lt;/em&gt; execution will paste contents to GitHub acount, which enables search, edit, comment etc. later on.&lt;/p&gt;

    &lt;p&gt;Actually since &lt;em&gt;gist&lt;/em&gt; supports &lt;em&gt;markdown&lt;/em&gt;, we can use &lt;em&gt;gist&lt;/em&gt; as a pure text blog.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;If once for a while, you don&apos;t want to expose your GitHub account on the Internet, you could add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; option to generate &lt;em&gt;bpaste&lt;/em&gt; service. You can also use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g -s gists&lt;/code&gt; to generate &lt;em&gt;anonymous gist&lt;/em&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-g&lt;/code&gt; option tells &lt;em&gt;wgetpaste&lt;/em&gt; to ignore configurations.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>robocopy</title>
   <link href="/2015/04/30/robocopy/"/>
   <updated>2015-04-30T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/04/30/robocopy</id>
   <content type="html">&lt;p&gt;Robust File Copy for Windows command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;robocopy&lt;/code&gt; can &lt;em&gt;mirror&lt;/em&gt; or &lt;em&gt;incrementally backup&lt;/em&gt; files/directories, with versitle parameters.&lt;/p&gt;

&lt;p&gt;The basic usage of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;robocopy&lt;/code&gt; is like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;robocopy &amp;lt;source-dir&amp;gt; &amp;lt;dest-dir&amp;gt; [file [file] ...] [options]

# robocopy d:\work e:\back *.txt *.doc *.bmp *.tif /s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Attention please: Windows does not differentiate letter case. Hence, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/s&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/S&lt;/code&gt; have the same effect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By default, file/directory to copy can be wildcards like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; (default to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.*&lt;/code&gt;; omitted usually). Read &lt;a href=&quot;http://basuya.blogspot.tw/2009/12/robocopy.html&quot;&gt;Robocopy 指令範例參考 (MIR問題很多，小心使用)&lt;/a&gt; or check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;robocopy /?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;robocopy&lt;/code&gt; will copy any name where the &lt;strong&gt;Timestamp or file size differs&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Timestamp refers to any of Creation Date, Last Modified Date or Last Access Date.&lt;/li&gt;
  &lt;li&gt;It does not care about whether the source or the dest is newer.&lt;/li&gt;
  &lt;li&gt;It does not count on any hash functions.&lt;/li&gt;
  &lt;li&gt;In order to avoid unnecessary copy, we should tune arguments accordingly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following is an example that mirrors a disk parittion:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /MIR = /E /PURGE
F:\&amp;gt;robocopy D:\ E:\ /MIR /XO

F:\&amp;gt;robocopy D:\ E:\ /MIR /XO /COPY:DAT /DCOPY:DAT [/MINAGE:1] /MAXLAD:7 /XA:SH /XD &quot;System Volume Information&quot; &quot;$RECYCLE.BIN&quot; /R:3 /W:10 /MT:16 /UNILOG+:F:\robocopy.log /TEE /Z
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/MIR&lt;/code&gt; mirrors a directory tree, equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/E /PURGE&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/XO&lt;/code&gt; skips older files from the source.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/COPY:DATS&lt;/code&gt; copies Data, Attributes, Timestamp and NTFS Security ACLs fo files.&lt;/p&gt;

    &lt;p&gt;By default, Security info of NTFS is not copied. However, the system may deny this for security considerations.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/DCOPY:DAT&lt;/code&gt; copies Data, Atrributes and Timestamp of directories.&lt;/p&gt;

    &lt;p&gt;By default, Timestamp is not copied.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/MINAGE:n&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/MAXAGE:n&lt;/code&gt; exclude files according to their Last Modified Date.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MINAGE:1&lt;/code&gt;  guarantees that files being updated today won&apos;t copied. On the contrary, MAXAGE skip files old enough.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; can be the number of days or date in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YYYYMMDD&lt;/code&gt; format. It should adapt to the bakcup &lt;em&gt;cron&lt;/em&gt; job.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/MINLAD:n&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/MAXLAD:n&lt;/code&gt; exclude files according to their Last Access Date.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/XA:SH&lt;/code&gt; excludes files with Hidden or System attributes.&lt;/p&gt;

    &lt;p&gt;In return, we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/IA:&lt;/code&gt; to copy only files with the specified attributes.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/XD &amp;lt;dir&amp;gt;&lt;/code&gt; excludes specific directories.&lt;/p&gt;

    &lt;p&gt;In return, we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/XF&lt;/code&gt; to exclude specific files.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/R:3&lt;/code&gt; retries 3 times on failed copies. By default, it is 1 million.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/W:10&lt;/code&gt; wait for 10 seconds between retries.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/MT:16&lt;/code&gt; creats 16 concurrent threads to copy files.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/UNILOG+:F:\robocopy.log&lt;/code&gt; redirects log to file with UNICODE encoding.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Z&lt;/code&gt; runs in &lt;em&gt;restartable&lt;/em&gt; mode such that we can resume the transfer in case it is interrupted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Linux alternative of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;robocopy&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt;. Please check &lt;em&gt;fmt.pdf&lt;/em&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Font</title>
   <link href="/2015/04/13/font/"/>
   <updated>2015-04-13T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/04/13/font</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#abc&quot; id=&quot;markdown-toc-abc&quot;&gt;ABC&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#fontconfig&quot; id=&quot;markdown-toc-fontconfig&quot;&gt;Fontconfig&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#per-user-installation&quot; id=&quot;markdown-toc-per-user-installation&quot;&gt;Per-user installation&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#system-wide-installation&quot; id=&quot;markdown-toc-system-wide-installation&quot;&gt;System-wide installation&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#xorg-fontpath&quot; id=&quot;markdown-toc-xorg-fontpath&quot;&gt;Xorg FontPath&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#per-user-configuration&quot; id=&quot;markdown-toc-per-user-configuration&quot;&gt;Per-user configuration&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#rehash-without-logout&quot; id=&quot;markdown-toc-rehash-without-logout&quot;&gt;Rehash without logout&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sphere---infinality&quot; id=&quot;markdown-toc-sphere---infinality&quot;&gt;Sphere - infinality&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#infinality-symlinks&quot; id=&quot;markdown-toc-infinality-symlinks&quot;&gt;&lt;em&gt;infinality&lt;/em&gt; symlinks&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#practice&quot; id=&quot;markdown-toc-practice&quot;&gt;Practice&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#reference&quot; id=&quot;markdown-toc-reference&quot;&gt;Reference:&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;abc&quot;&gt;ABC&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Applications use fonts by &lt;em&gt;font systems&lt;/em&gt;. There are two font systems, namely XLFD and XFT.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;X Logical Font Description (XLFD) is an old font system, originally designed for &lt;em&gt;bitmap&lt;/em&gt; fonts. Later on, XLFD adds in support for scalable fonts like PostScript Type1, TrueType (.ttf) and even newer OpenType (.otf). XLFD fonts is usually located under &lt;em&gt;/usr/share/fonts&lt;/em&gt; like 75dpi, 100dpi etc. An XLFD font name is a long string, as below:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The name contains fourteen hyphen-separated fields, with each field representing a property of the font. Not all fields are required to be present. In Emacs, we can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x =&lt;/code&gt; over a character so show the XLFD name.&lt;/p&gt;

    &lt;p&gt;XLFD is almost depcreted but still required by ancient programs like &lt;em&gt;xterm&lt;/em&gt;, &lt;em&gt;urxvt&lt;/em&gt; and GTK+1. To set XLFD for X, we use &lt;em&gt;xfontsel&lt;/em&gt;, and &lt;em&gt;xlsfonts&lt;/em&gt;.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;For X, we can use &lt;em&gt;xset&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;XFT is a newer font system, supporting much more font types. &lt;a href=&quot;https://unix.stackexchange.com/a/398739/74407&quot;&gt;depending&lt;/a&gt; on Fontconfig&apos;s &lt;em&gt;matching&lt;/em&gt; feature and Freetype&apos;s font &lt;em&gt;rendering&lt;/em&gt; feature. Freetype makes fonts (e.g. anti‑aliasing and sub‑pixel rasterization) look smooth and beautiful.&lt;/p&gt;

    &lt;p&gt;We configure Fontconfig to use XFT &lt;em&gt;/etc/fonts/fonts.conf&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Application decides to use which font system. Almost all applications use XFT now, Xorg included. Emacs supports both XLFD and XFT (try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x: describe-font&lt;/code&gt;).&lt;/p&gt;

    &lt;p&gt;However, we may tune FontPath in &lt;em&gt;xorg.conf&lt;/em&gt; covering bitmap fonts for ancient programs. Most of the time, we do not include XFT fonts in &lt;em&gt;xorg.conf&lt;/em&gt;. To check fonts knowns to X:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ grep /fonts /var/log/Xorg.0.log
or
$ xset q
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;fontconfig&quot;&gt;Fontconfig&lt;/h1&gt;

&lt;p&gt;Commands like &lt;em&gt;fc-list&lt;/em&gt;, &lt;em&gt;fc-list&lt;/em&gt;, &lt;em&gt;fc-query&lt;/em&gt;, &lt;em&gt;fc-match&lt;/em&gt; etc. can help check fonts&apos; information.&lt;/p&gt;

&lt;p&gt;This section demonstrates how to manully install personal fonts.&lt;/p&gt;

&lt;h2 id=&quot;per-user-installation&quot;&gt;Per-user installation&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/.local/share/fonts/winfonts
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/.local/share/fonts/winfonts
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; /path/to/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;abc.ttf,123.otf&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;fc-cache &lt;span class=&quot;nt&quot;&gt;-fv&lt;/span&gt; ./&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkfontscale ./ &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; mkfontdir ./ &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; xset fp rehash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;For manually copied fonts, we have to create the font cache with &lt;em&gt;fc-cache&lt;/em&gt;. Font cache is to speed up font loading. Package manager (i.e. &lt;em&gt;emerge&lt;/em&gt;) takes care of it automatically.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;mkfontscale&lt;/em&gt; and &lt;em&gt;mkfontdir&lt;/em&gt; will create file &lt;em&gt;fonts.scale&lt;/em&gt; and &lt;em&gt;fonts.dir&lt;/em&gt; for XLFD fonts. &lt;em&gt;xset fp rehash&lt;/em&gt; makes new fonts immediately available to current X sessions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;system-wide-installation&quot;&gt;System-wide installation&lt;/h2&gt;

&lt;p&gt;To manually install fonts for the whole system is similar except that fonts are put under &lt;em&gt;/usr/share/fonts/&lt;/em&gt; or &lt;em&gt;/opt/fonts/&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/ &lt;span class=&quot;c&quot;&gt;# mkdir /opt/fonts/winfonts&lt;/span&gt;
/ &lt;span class=&quot;c&quot;&gt;# chmod 755 /opt/fonts/winfonts&lt;/span&gt;
/ &lt;span class=&quot;c&quot;&gt;# cd /opt/fonts/winfonts&lt;/span&gt;
/ &lt;span class=&quot;c&quot;&gt;# cp /path/to/{abc.ttf,123.otf} ./&lt;/span&gt;
/ &lt;span class=&quot;c&quot;&gt;# chmod -R 644 .&lt;/span&gt;
/ 
/ &lt;span class=&quot;c&quot;&gt;# fc-cache -fv ./*&lt;/span&gt;
/ &lt;span class=&quot;c&quot;&gt;# mkfontscale ./ &amp;amp;&amp;amp; mkfontdir ./&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;xorg-fontpath&quot;&gt;Xorg FontPath&lt;/h1&gt;

&lt;p&gt;Most of time, Fontconfig works out of box without any further configuration. To support ancient applications that use XLFD, we might need to tune &quot;FontPath&quot;.&lt;/p&gt;

&lt;p&gt;For Xorg to load fonts directly (as opposed to the use of a font server - XFT), the directory for your newly added font must be added with a &quot;FontPath&quot; entry. This entry is located in the &quot;Files&quot; section of Xorg configuration file. An official example is &lt;em&gt;/usr/share/doc/xorg-server-1.18.4/xorg.conf.example.bz2&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Create &lt;em&gt;/etc/X11/xorg.conf.d/10-fontpath.conf&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Section &quot;Files&quot;
# Multiple FontPath entries are allowed (which are concatenated together),
# as well as specifying multiple comma-separated entries in one FontPath
# command (or a combination of both methods).
# The default path is shown here.
#    FontPath	/usr/share/fonts/misc/,/usr/share/fonts/TTF/,/usr/share/fonts/OTF/,/usr/share/fonts/Type1/,/usr/share/fonts/100dpi/,/usr/share/fonts/75dpi/

    FontPath &quot;/usr/share/fonts/misc&quot;
    FontPath &quot;/usr/share/fonts/100dpi,/usr/share/fonts/75dpi&quot;
    FontPath &quot;/usr/share/fonts/util&quot;
    FontPath &quot;/usr/share/fonts/encodings&quot;
    ...
    FontPath &quot;/usr/share/fonts/winfonts&quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&quot;FontPath&quot; entry can be a single font path or multiple comma-separated font paths (or a combination of both). Font paths must be quoted.&lt;/li&gt;
  &lt;li&gt;The default pathes (i.e. &lt;em&gt;100dpi&lt;/em&gt;, &lt;em&gt;75dpi&lt;/em&gt; etc.) are always scanned.&lt;/li&gt;
  &lt;li&gt;Pathes lack &lt;em&gt;fonts.scale&lt;/em&gt; (&lt;em&gt;mkfontscale&lt;/em&gt;) and &lt;em&gt;fonts.dir&lt;/em&gt; (&lt;em&gt;mkfontdir&lt;/em&gt;) are neglected.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;per-user-configuration&quot;&gt;Per-user configuration&lt;/h2&gt;

&lt;p&gt;Settings Font Path under &lt;em&gt;/etc/X11/xorg.conf.d/&lt;/em&gt; are system-wide effective. For per-user setting, add&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;xset +fp /usr/share/fonts/dejavu/           # Prepend a custom font path to Xorg&apos;s list of known font paths
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;to &lt;em&gt;~/.xinitrc&lt;/em&gt;. Alternatively, execute it on command line.&lt;/p&gt;

&lt;p&gt;To remove a Font Path, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-fp&lt;/code&gt; instead.&lt;/p&gt;

&lt;h2 id=&quot;rehash-without-logout&quot;&gt;Rehash without logout&lt;/h2&gt;

&lt;p&gt;After the setting, we want immediate effect:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# xsetq fp rehash&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;sphere---infinality&quot;&gt;Sphere - infinality&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;infinality&lt;/em&gt; USE can be enabled globally in &lt;em&gt;/etc/portage/make.conf&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;media-libs/freetype adobe-cff infinality&quot; &amp;gt; /etc/portage/package.use/freetype&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -av media-libs/freetype&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eselect fontconfig list&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eselect fontconfig enable 52-infinality.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;fontconfig-infinality&lt;/em&gt; will draw in its own settings (&lt;em&gt;/etc/fonts/infinality&lt;/em&gt;) which will interfere with the other fontconfig configuration. It&apos;s recommended to disable most of Fontconfig options while keeping &lt;em&gt;52-infinality.conf&lt;/em&gt;. Specially, configurations related to specific fonts can be kept like &lt;em&gt;62-croscore-*&lt;/em&gt;.conf* and &lt;em&gt;57-dejavu-*.conf&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You will find &lt;em&gt;fontconfig&lt;/em&gt; (&lt;em&gt;/etc/fonts/&lt;/em&gt;) and &lt;em&gt;infinality&lt;/em&gt; (&lt;em&gt;/etc/fonts/infinality/&lt;/em&gt;) has the nearly the same directory architecture. The &lt;em&gt;conf.d&lt;/em&gt; sub-directory stores the selected symlinks, while &lt;em&gt;conf.avail&lt;/em&gt; (or &lt;em&gt;conf.src&lt;/em&gt;) stores all existing configurations. We use &lt;em&gt;eselect&lt;/em&gt; which chooses and creates symbolic links under &lt;em&gt;conf.d&lt;/em&gt; sub-directory.&lt;/p&gt;

&lt;p&gt;Optionally, refer to reference number 3, set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;embeddedbitmap&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/fonts/infinality/infinality.conf&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;infinality-symlinks&quot;&gt;&lt;em&gt;infinality&lt;/em&gt; symlinks&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# eselect lcdfilter list&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eselect lcdfilter set 14, set to *windows-7*&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eselect infinality list&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eselect infinality set to *win7*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure &lt;em&gt;lcdfilter&lt;/em&gt; and &lt;em&gt;infinality&lt;/em&gt; choose the same category.&lt;/p&gt;

&lt;h1 id=&quot;practice&quot;&gt;Practice&lt;/h1&gt;

&lt;p&gt;Practice from &lt;a href=&quot;http://www.jinbuguo.com/gui/linux_fontconfig.html&quot;&gt;Jin Buguo Linux字体美化实战(Fontconfig配置)&lt;/a&gt; is outdated. However, I want to use his recommended fonts, except the Korean ones. Additionally, we need to install &lt;em&gt;noto-fonts-cjk&lt;/em&gt; as Firefox may fallback to those fonts.&lt;/p&gt;

&lt;p&gt;Ancient applications using XLFD refer to X11 Font Path directly. Make sure &lt;em&gt;fonts.scale&lt;/em&gt; (by &lt;em&gt;mkfontscale) and *fonts.dir&lt;/em&gt; (by &lt;em&gt;mkfontdir&lt;/em&gt;) exist under each directory of font directory. Paths under &lt;em&gt;/opt/fonts/&lt;/em&gt; can be appended to Font Path if you&apos;d like.&lt;/p&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference:&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://ted.is-programmer.com/categories/1547/posts&quot;&gt;Gentoo Linux on T43 (7) 中文字体&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.freebsdchina.org/forum/viewtopic.php?t=34824&amp;amp;start=0&amp;amp;postdays=0&amp;amp;postorder=asc&amp;amp;highlight=&quot;&gt;字体配置local.conf详解[带Win效果和AA效果]&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://groups.google.com/forum/#!topic/gentoo-china/gzW8mg9OIhg&quot;&gt;gentoo 下字体美化该如何设置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/kidlj/f30e82c2c6f064990596&quot;&gt;在Gentoo上配置Infinality&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Fontconfig&quot;&gt;Gentoo Fontconfig&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Gentoo Installation</title>
   <link href="/2015/03/25/gentoo-installation/"/>
   <updated>2015-03-25T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/03/25/gentoo-installation</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Gentoo installation along with Windows 8.1 and Ubuntu 14.04 with UEFI booting.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;tips&quot;&gt;Tips&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Follow &lt;a href=&quot;https://wiki.gentoo.org/wiki/Handbook:AMD64&quot;&gt;Handbook&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;To &lt;em&gt;emerge&lt;/em&gt; packages, you&apos;d better read ArchWiki.&lt;/li&gt;
  &lt;li&gt;Ref:
    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;http://vminko.org/gentoo_manuals/thinkpad_x200&quot;&gt;Gentoo on a ThinkPad X200&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Lenovo_ThinkPad_T440s&quot;&gt;thinkpad t440s gentoo&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://www.thinkwiki.org/wiki/Installing_Gentoo_on_a_ThinkPad_X220&quot;&gt;Installing Gentoo on a ThinkPad X220&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;livedvd-usb-stick&quot;&gt;LiveDVD USB stick&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Download the LiveDVD like &lt;em&gt;livedvd-amd64-multilib-20140826.iso&lt;/em&gt; instead of Minimal installation CD like &lt;em&gt;install-amd64-minimal-20150319.iso&lt;/em&gt;.
    &lt;ol&gt;
      &lt;li&gt;Minimal CD cannot generates UEFI bootable USB stick.&lt;/li&gt;
      &lt;li&gt;LiveDVD gives desktop environment to ease network connection and WWW surfing.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Create UEFI USB stick. Similar tools are:
    &lt;ol&gt;
      &lt;li&gt;Rufus;&lt;/li&gt;
      &lt;li&gt;UNetbootin;&lt;/li&gt;
      &lt;li&gt;Universal USB Installer;&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;diskpart&lt;/em&gt; terminal command;&lt;/li&gt;
      &lt;li&gt;Just copy the ISO contents into a FAT32 format USB stick;&lt;/li&gt;
      &lt;li&gt;Use &lt;em&gt;dd&lt;/em&gt; command;&lt;/li&gt;
      &lt;li&gt;Ubuntu disk creater.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Boot into the KDE desktop environment with USB stick made before. By default, there is no password required for account &lt;em&gt;gentoo&lt;/em&gt;.
    &lt;ol&gt;
      &lt;li&gt;The very first thing is to connect to Wi-Fi or Ethernet through networkmanager.&lt;/li&gt;
      &lt;li&gt;Use shortcut F12 to Open/Retract Yakuake/Guake terminal in KDE destop.&lt;/li&gt;
      &lt;li&gt;Refer to &lt;a href=&quot;https://www.gentoo.org/proj/en/pr/releases/10.0/faq.xml&quot;&gt;Gentoo Ten LiveDVD Frequently Asked Questions&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo su -&lt;/code&gt; to &lt;em&gt;root&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;You can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;passwd USERNAME&lt;/code&gt; to change the password of &lt;em&gt;gentoo&lt;/em&gt;. As &lt;em&gt;root&lt;/em&gt;, you can change any account passworld by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;passwd username&lt;/code&gt;. All the password thing within the LiveDVD environment is volatile.&lt;/p&gt;

    &lt;p&gt;The command prompt is &lt;em&gt;livecd ~ #&lt;/em&gt; different from the handbook one - &lt;em&gt;root #&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;disk-preparation&quot;&gt;Disk preparation&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parted -a optimal /dev/sda&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fdisk /dev/sda&lt;/code&gt;. Erase &lt;em&gt;/dev/sda10&lt;/em&gt; (NTFS partition) to install Gentoo on.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parted&lt;/code&gt; takes effect immediately without final confirmation like &lt;em&gt;fdisk&lt;/em&gt;. Read &lt;a href=&quot;/2015/07/23/kali-usb-persistence/&quot;&gt;Kali Linux Live USB Persistence&lt;/a&gt; first.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. &lt;span class=&quot;c&quot;&gt;# parted -a optimal /dev/sda&lt;/span&gt;
2. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;help
&lt;/span&gt;2. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p
3. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; unit MiB
3. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;10
3. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p
4. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary 309921MiB 310049MiB, create a boot partition sda10 &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;Gentoo
5. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p
6. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; name 10 &lt;span class=&quot;s1&quot;&gt;&apos;Gentoo boot partition&apos;&lt;/span&gt;
7. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; mkpart primary 310049MiB &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt;, create root partition sda12 &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;Gentoo
8. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p
9. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; name 12 &lt;span class=&quot;s1&quot;&gt;&apos;Gentoo root partition&apos;&lt;/span&gt;
10. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; p
11. &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;parted&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; q
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The partition &lt;em&gt;Type&lt;/em&gt; is &lt;em&gt;Basic data partition&lt;/em&gt; when checking with &lt;em&gt;fdisk /dev/sda&lt;/em&gt;. You change that through Disk GUI application under Ubuntu.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Newly created &lt;em&gt;/dev/sda10&lt;/em&gt; will be the &lt;em&gt;boot&lt;/em&gt; partition while &lt;em&gt;/dev/sda12&lt;/em&gt; the &lt;em&gt;root&lt;/em&gt; partition.&lt;/p&gt;

    &lt;p&gt;We don&apos;t create Swap (&lt;em&gt;sda7&lt;/em&gt;) or EFI (&lt;em&gt;sda2&lt;/em&gt;) partition. Just share them with Ubuntu and Windows. You can also create a separate home partition, say &lt;em&gt;sda13&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Format the new partition. You are suggested to format boot partition as &lt;em&gt;ext2&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkfs.ext2 /dev/sda10&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkfs.ext4 /dev/sda12&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkfs.ext4 /dev/sda13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;swap&lt;/em&gt; partition needs &lt;em&gt;activate&lt;/em&gt;d&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-bass&quot;&gt;# mkswap /dev/sda7 (opt)
# swapon /dev/sda7
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;If you prefer an independent &lt;em&gt;swap&lt;/em&gt; partition, &lt;em&gt;mkswap&lt;/em&gt; to format it firstly.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mount partitions.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mount /dev/sda12 /mnt/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkdir -p /mnt/gentoo/boot/efi &amp;amp;&amp;amp; mount /dev/sda10 /mnt/gentoo/boot &amp;amp;&amp;amp; mount /dev/sda2 /mnt/gentoo/boot/efi&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkdir /mnt/gentoo/home &amp;amp;&amp;amp; mount /dev/sda13 /mnt/gentoo/home&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;install-stage3&quot;&gt;Install &lt;em&gt;stage3&lt;/em&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Check date and time using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;date&lt;/code&gt; command. Set by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;date MMDDhhmm&lt;/code&gt; if it&apos;s incorrect.&lt;/li&gt;
  &lt;li&gt;Downloading and verify &lt;em&gt;stage3&lt;/em&gt; tarball. Usually, it&apos;s downloaded beforehand along with LiveDVD ISO.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Now unpack the downloaded stage onto the system.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd /mnt/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# tar xvjpf /mnt/cdrom/stage3-amd64-20150319.tar.bz2 --xattrs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; stands for Extract;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v&lt;/code&gt; for Verbose to see what happens during the extraction process (optional);&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j&lt;/code&gt; to Decompress with &lt;em&gt;bzip2&lt;/em&gt;;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p&lt;/code&gt; for Preserve permissions;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; denotes that we want to extract a File, not standard input;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--xattrs&lt;/code&gt; includes the extended attributes stored in the archive as well.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;makeconf&quot;&gt;&lt;em&gt;make.conf&lt;/em&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CFLAGS&lt;/code&gt; == &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CXXFLAGS&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;Check your CPU architecture to set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-march=&lt;/code&gt; parameter. Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/Safe_CFLAGS#Intel&quot;&gt;Intel&lt;/a&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep -m1 -A3 &quot;vendor_id&quot; /proc/cpuinfo&lt;/code&gt; offers CPU architecure. That link also teach you how to precisely detect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-march=&lt;/code&gt; parameter by touching, compiling and comparing two &lt;em&gt;.gcc&lt;/em&gt; files.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;CFALGS=&quot;-march=sandybridge -O2 -pipe&quot;&lt;/li&gt;
      &lt;li&gt;CXXFLAGS=&quot;${CFLAGS}&quot;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAKEOPTS&lt;/code&gt; variable defines how many parallel compilations should occur when emerging packages.&lt;/p&gt;

    &lt;p&gt;The recommended value is the number of logical processors in the CPU plus 1. But this rule is outdated. I have 4GB memory and &lt;em&gt;swap/swapfile&lt;/em&gt; enabled, &lt;em&gt;emerge&lt;/em&gt; will make use of &lt;em&gt;swap&lt;/em&gt; havily.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;swap&lt;/em&gt; naturally slows down performance but supports more parallel tasks. So turn down to 2 or even 1 to reduce usage of &lt;em&gt;swap&lt;/em&gt; file.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Add a line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MAKEOPTS=&quot;-j3&quot;&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;The boot screen shows several penguins, that is the number of logical hardware cores. If kernel &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X86_SYSFB&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FB_SIMPLE&lt;/code&gt; were turned off, you could not see boot penguins.&lt;/li&gt;
      &lt;li&gt;This value does not apply to &lt;em&gt;kernel compiling&lt;/em&gt;. We explicitly specify &lt;em&gt;make -j3&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/MAKEOPTS&quot;&gt;MAKEOPTS&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CPU_FLAGS_X86&lt;/code&gt;: The &apos;USE&apos; flags corresponding to the CPU instruction sets and other features specific to the &lt;em&gt;x86/amd64&lt;/em&gt; architecture are &lt;em&gt;being&lt;/em&gt; moved into a separate USE flag group called &lt;em&gt;CPU_FLAGS_X86&lt;/em&gt;.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Refer to &lt;a href=&quot;https://www.gentoo.org/support/news-items/2015-01-28-cpu_flags_x86-introduction.html&quot;&gt;cpu_flags_x86 instruction&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;Emerge &lt;em&gt;app-portage/cpuinfo2cpuflags&lt;/em&gt; and run in LiveDVD. Edit &apos;make.conf&apos; to set &lt;em&gt;CPU_FLAGS_X86&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Up to now, some packages in &lt;em&gt;portage&lt;/em&gt; and overlays are not yet migrating those flags from &apos;USE&apos; to &apos;CPU_FLAGS_X86&apos;. So:&lt;/li&gt;
      &lt;li&gt;Remove the old CPU specific flags from &apos;USE&apos;. Then add &lt;em&gt;${CPU_FLAGS_X86}&lt;/em&gt; to &apos;USE&apos;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;chrooting&quot;&gt;Chrooting&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cp -L /etc/resolv.conf /mnt/gentoo/etc/&lt;/code&gt;,  to ensure that networking after chrooting.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mounting the necessary filesystems.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mount -t proc proc /mnt/gentoo/proc&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount --rbind /sys /mnt/gentoo/sys&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount --make-rslave /mnt/gentoo/sys&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount --rbind /dev /mnt/gentoo/dev&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount --make-rslave /mnt/gentoo/dev&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# chroot /mnt/gentoo /bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# source /etc/profile &amp;amp;&amp;amp; export PS1=&quot;(chroot) $PS1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;mirrors-and-sync&quot;&gt;Mirrors and Sync&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Selecting mirrors&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mirrorselect -s3 -b10 -o -D &amp;gt;&amp;gt; /mnt/gentoo/etc/portage/make.conf (opt)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Choose the 3 fastest mirrors for package sources downloading. This will takes around 10 minutes. So usually, we just manually choose 3 physically close servers.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;[deprecated] &lt;s&gt;Portage sync&lt;/s&gt;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mirrorselect -i -r -o &amp;gt;&amp;gt; /mnt/gentoo/etc/portage/make.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Selects the &lt;em&gt;rsync&lt;/em&gt; server to use when synchronizing portage tree. It is recommended to choose a &lt;em&gt;rotation link&lt;/em&gt;, such as &lt;em&gt;rsync.us.gentoo.org&lt;/em&gt;, rather than choosing a single mirror (i.e. &lt;em&gt;ftp&lt;/em&gt;). This helps spread out the load and provides a fail-safe in case a specific mirror is offline.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The new plug-in &lt;a href=&quot;https://wiki.gentoo.org/wiki/Project:Portage/Sync&quot;&gt;sync system&lt;/a&gt; (&lt;em&gt;&amp;gt;=sys-apps/portage-2.2.16&lt;/em&gt;)&lt;/p&gt;

    &lt;p&gt;The new &lt;em&gt;plug-in sync system&lt;/em&gt; currently supports &lt;em&gt;rsync, git, svn, websync, webrsync, cvs, laymansync&lt;/em&gt; synchronizing types. And configurations reside now under &lt;em&gt;/etc/portage/repos.conf/&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;After installing &lt;em&gt;stage3&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mkdir /mnt/gentoo/etc/portage/repos.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cp /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;portage-tree&quot;&gt;Portage tree&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Portage snapshot&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge-webrsync&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;webrsync&lt;/em&gt; type is used to create a complete Portage tree. It might complain about a missing &lt;em&gt;/usr/portage/&lt;/em&gt; location. This is to be expected and nothing to worry about - it will be created on demand.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Profile&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# eselect profile list&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eselect profile set 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Choose the &lt;em&gt;desktop&lt;/em&gt; profile instead of &lt;em&gt;desktop/gnome&lt;/em&gt; or &lt;em&gt;desktop/kde&lt;/em&gt;. We will install XFCE later on.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;USE flags&lt;/p&gt;

    &lt;p&gt;Try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emerge --info | grep ^USE&lt;/code&gt; to check USEs set by profile and &lt;em&gt;make.conf&lt;/em&gt;. Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/Xfce/Guide#The_basics&quot;&gt;Xfce/Guide&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;USE=&quot;${CPU_FLAGS_X86} -bindist -qt4 -libav vaapi&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;By default, &lt;em&gt;bindist&lt;/em&gt; is enabled by &lt;em&gt;stage3&lt;/em&gt;&apos;s default &lt;em&gt;make.conf&lt;/em&gt;. If we don&apos;t plan to distribute packages, remove it. &lt;em&gt;bindist&lt;/em&gt; may cause conflicts, i.e. between &lt;em&gt;openssh&lt;/em&gt; and &lt;em&gt;openssl&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;localization&quot;&gt;Localization&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://unix4lyfe.org/time/&quot;&gt;Time&lt;/a&gt;
    &lt;ol&gt;
      &lt;li&gt;Prime Meridian was (arbitrarily) chosen to pass through the Royal Observatory in Greenwich.&lt;/li&gt;
      &lt;li&gt;UTC (previously called Greenwich Mean Time GMT): time at zero degrees longitude (the Prime Meridian) is called Coordinated Universal Time.&lt;/li&gt;
      &lt;li&gt;Unix time: Measured as the number of seconds since epoch (the beginning of 1970 in UTC). Unix time is not affected by time zones or daylight saving.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Local Time (UTC + Timezone) is what we use daily.&lt;/p&gt;

        &lt;p&gt;Setting operating Software Time equal correctly to Local Time is our goal.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Hardware Time resides on BIOS, which can be set manually and updated by operating system. Both Windows and Linux sets Software Time based on Hardware Time.&lt;/p&gt;

        &lt;p&gt;It&apos;s regarded as &lt;em&gt;permanent placeholder&lt;/em&gt; to set Software Time.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Windows treats Hardware Time as Local Time and sets Software Time identically to Hardware Time without any translation on boot. Timezone is to synchronize time with time server. Upon shutdown, Windows writes back Software Time to Hardware Time.&lt;/li&gt;
      &lt;li&gt;Linux treats Hardware Time as UTC and adds Timezone (i.e. +8) to Hardware Time on boot. Similarly, Software Time is written back to Hardware Time.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Suppose Windows Software Time and Hardware Time are correctly synched to Local Time, Linux (dual boot installation afterwards) Software Time will be Hardware Time + Timezone = Windows Software Time + Timezone = Local Time + 2xTimezone. So usually Linux Software Time is ahead of Localtion for Timezone.&lt;/p&gt;

        &lt;p&gt;If we shutdown Linux and boot Windows, Windows Software Time will be ahead of Local Time too. Each time we switch back and forth, Software Time will increase linearly by Timezone step.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;We must tell Linux that Hardware Time is Local Time instead of UTC &lt;em&gt;before&lt;/em&gt; Software Timezone is configured.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;hwclock&lt;/p&gt;

    &lt;p&gt;Set &lt;em&gt;clock=local&lt;/em&gt; in &lt;em&gt;/etc/conf.d/hwclock&lt;/em&gt;. We can find other options concerning reading/updating Hardware Time.&lt;/p&gt;

    &lt;p&gt;Afterwards, set timezone information.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Timezone&lt;/p&gt;

    &lt;p&gt;This step should be after &lt;em&gt;/etc/conf.d/hwclock&lt;/em&gt; update. Otherwise the Linux Software Time is usually ahead of local time by 8 hours, thus resulting in portage tree time stamp issues.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ls /usr/share/zoneinfo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# echo &quot;Asia/Shanghai&quot; &amp;gt; /etc/timezone&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge --config sys-libs/timezone-data&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# date&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.ibm.com/developerworks/cn/linux/l-cn-linuxglb/&quot;&gt;locale&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;The &lt;em&gt;locale&lt;/em&gt; format is like &lt;em&gt;xx_YY.ZZ&lt;/em&gt;, where &lt;em&gt;xx&lt;/em&gt; and &lt;em&gt;YY&lt;/em&gt; denote lanugage code and country code respectively. &lt;em&gt;ZZ&lt;/em&gt; stands for charset (encoding/decoding). &lt;em&gt;xx&lt;/em&gt; and &lt;em&gt;YY&lt;/em&gt; mainly affects GUI (DE, app menus etc.), while &lt;em&gt;ZZ&lt;/em&gt; takes care of encoding/decoding.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;eselect locale set&lt;/em&gt; defines all locale settings at once by &lt;em&gt;LANG&lt;/em&gt; varaible while allowing further individual customization via the &lt;em&gt;LC_*&lt;/em&gt; sub-options (i.e. &lt;em&gt;LC_CTYPE&lt;/em&gt;).&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cat /usr/share/i18n/SUPPORTED \| grep zh_CN &amp;gt;&amp;gt; /etc/locale.gen&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# uncomment en_US.UTF-8 UTF-8&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# locale-gen&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# locale -a&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eselect locale list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;In the 3rd step, if reminded to run &quot;&lt;em&gt;. /etc/profile&lt;/em&gt;&quot; to reload the variable, just remember &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;export PS1=&quot;(chroot) $PS1&quot;&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;Use &lt;em&gt;xx_YY.UTF-8&lt;/em&gt; (some applications does NOT recognize &lt;em&gt;xx_YY.utf8&lt;/em&gt;) instead of the illegal format &lt;em&gt;xx_YY.UTF8&lt;/em&gt;. How to achieve this? Use the &lt;em&gt;free form&lt;/em&gt; of Gentoo &lt;em&gt;eselect&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# eselect locale set en_US.UTF-8
# locale
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;LC_*&lt;/em&gt; sub-options can be further set in &lt;em&gt;/etc/env.d/02locale&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LANG=&quot;en_US.UTF-8&quot;
LC_COLLATE=&quot;C&quot;
LC_CTYPE=&quot;zh_CN.UTF-8&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If you don&apos;t have privileged access, &lt;em&gt;export&lt;/em&gt; them in shell RC file like &lt;em&gt;.bashrc&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Remember to&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# env-update &amp;amp;&amp;amp; source /etc/profile &amp;amp;&amp;amp; export PS1=&quot;(chroot) $PS1&quot;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# locale&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Chinese&lt;/p&gt;

    &lt;p&gt;Why English display is not a concern? You may say that English is the mostly used accross the world and hence mostly used by programmers and the applications thereof. Yep, that&apos;s right but superficial. The underlying core is that ASCII table (English characters) is covered by nearly all encoding schemes present, GB2312/GBK/GB18030 included! No matter which encoding scheme is chosen, English is always correctly displayed.&lt;/p&gt;

    &lt;p&gt;To be specific, language display is divided into two aspects:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;GUI (i.e. menu, popup box, botton, log etc.).&lt;/li&gt;
      &lt;li&gt;File content which is what we refer to without explicit explanation (i.e. a HTML page).&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Let&apos;s talk about GUI first. You may be confused. Most applications GUI use ASCII characters (i.e. popup error dialog), thus correctly displayed no matter what system locale is set. But applications written for Chinese like QQ use Chinese GUI by default. What if the author could not be bothered to offer English GUI? Then we have to tune system locale to Chinese.&lt;/p&gt;

    &lt;p&gt;What if you would like more Chinese on your system GUI, which looks confortable? That&apos;s where &lt;em&gt;nls&lt;/em&gt; and &lt;em&gt;l10n_*&lt;/em&gt; (&lt;em&gt;linguas_*&lt;/em&gt; will be deprecated) USEs play a role. Many applications supports either &lt;em&gt;nls&lt;/em&gt; or &lt;em&gt;l10n&lt;/em&gt;, which is the part users can control. The localized/translated GUI messages is stored in */usr/share/locale/&lt;locale&gt;/LC_MESSAGES/&lt;package&gt;.mo* files. *nls* installs all possible locale messages, while *l10n_\** only installs the locale message specified by USE. The system locale must be *LANG=zh_CN.ZZ* to let installed locale messages displayed, where ZZ charset must covers zh_CN characters (GB2312 GBK GB18030). If you only set sub-option *LC_CTYPE=zh_CN.ZZ*, then GUI sticks to English.&lt;/package&gt;&lt;/locale&gt;&lt;/p&gt;

    &lt;p&gt;When it comes to file content display/updating, it depends on the context. Client browser decodes HTM page by the &lt;em&gt;charset&lt;/em&gt; tag. Emacs is smtart at detecting file encoding. Mousepad is stupid and always decode by system locale. And will ask for user confirmation upon failure. However, for Unicode-based encoding, it&apos;s easy to guess the encoding through BOM. Modern applications is smart at detection. If the application fails to detect file encoding, it may default to &lt;em&gt;ZZ&lt;/em&gt; part of locale, to which many comand line tools belongs.&lt;/p&gt;

    &lt;p&gt;Let&apos;s go on details of &lt;em&gt;ZZ&lt;/em&gt; part. For Chinese, it should be one of GB2312, GBK, GB18030 and UTF-8. Apart from the fallback decoding role, it mainly determine encoding of user generated contents (i.e. default encoding of new file).&lt;/p&gt;

    &lt;p&gt;Remember that:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Chinese characters are encoded and stored. Upon display, the encoding scheme should be found (by GTK/QT, text editor, browser, even by user involvement).&lt;/li&gt;
      &lt;li&gt;The advantage of setting &lt;em&gt;ZZ&lt;/em&gt; to UTF-8 is that it&apos;s widely used and reduces mojibak.&lt;/li&gt;
      &lt;li&gt;UTF-8 requires more disk space (50% higher) for CJK characters.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;It&apos;s not over yet. Up to now, only character encoding is detected. In order to display the character, relevant font should be matched (i.e. by Fontconfig). Translation between the character encoding and &lt;em&gt;glyph&lt;/em&gt; is done through font&apos;s intermediate &lt;em&gt;charmap/cmap/bmp&lt;/em&gt; files. &lt;em&gt;cmap&lt;/em&gt; is  a table mapping character encoding to glyph&apos;s &lt;em&gt;internal index&lt;/em&gt;. Each font may include multiple &lt;em&gt;cmap&lt;/em&gt; files corresponding to different character encodings (i.e. GBK, UTF-8). Then font engine (i.e. FreeType2) renders the returned &lt;em&gt;glyph&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Attention, &lt;em&gt;cmap&lt;/em&gt; itself is encoded as well, mostly by Unicode (namely UTF-16/UCS-2, NOT UTF-8).&lt;/p&gt;

    &lt;p&gt;Details on XFT, refer to &lt;a href=&quot;/2015/04/13/fontconfig/&quot;&gt;fontconfig&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;kernel-building&quot;&gt;Kernel building&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Kernel sources tree&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt sys-kernel/gentoo-sources&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# eselect kernel list/set&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ls -l /usr/src &amp;amp;&amp;amp; cd /usr/src/linux;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# git apply [--whitespace=warn] [--numstat] [--check] &amp;lt; /path/to/cjktty.patch&lt;/span&gt;
or
&lt;span class=&quot;c&quot;&gt;# patch [--dry-run] -p1 &amp;lt; /path/to/cjktty.patch (opt)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;For the first time we install kernel sources, &lt;em&gt;/etc/src/linux&lt;/em&gt; symlink is created automatically.&lt;/p&gt;

    &lt;p&gt;If possible, apply kernel patches like &lt;em&gt;cjktty.patch&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Tips
    &lt;ol&gt;
      &lt;li&gt;You&apos;d best have a &lt;em&gt;.config&lt;/em&gt; backup to start with.&lt;/li&gt;
      &lt;li&gt;If possible, try &lt;em&gt;sys-apps/pciutils, sys-apps/usbutils, and sys-apps/{lshw,dmidecode}&lt;/em&gt; in LiveDVD. Don&apos;t emerge those packages in &lt;em&gt;chroot&lt;/em&gt;, it&apos;s not necessary.&lt;/li&gt;
      &lt;li&gt;During kernel config, search the kernel options on page &lt;a href=&quot;http://www.jinbuguo.com/kernel/longterm-3_10-options.html&quot;&gt;Linux-3.10-x86_64 内核配置选项简介&lt;/a&gt; and refer to LiveDVD&apos;s configuration.&lt;/li&gt;
      &lt;li&gt;Try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lspci -n&lt;/code&gt; and paste it&apos;s output to &lt;a href=&quot;http://kmuto.jp/debian/hcl&quot;&gt;device driver check page&lt;/a&gt;; that site gives kernel options that must be enabled.&lt;/li&gt;
      &lt;li&gt;We can refer to the LiveDVD&apos;s kernel config directly.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Search with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;. When search &quot;snd-hda-intel&quot;, replace the hypen with dash.&lt;/p&gt;

        &lt;p&gt;Usually there are several search outputs numerated (1, 2, 3 …). Press the number to enter the kernel option.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;em&gt;exit&lt;/em&gt; or two successive ESCs to get back.&lt;/li&gt;
      &lt;li&gt;When confronted with issues related to kernel options, we can choose M instead of Y which might be a solution.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;.config&lt;/em&gt; backup&lt;/p&gt;

    &lt;p&gt;Suppose we have an old &lt;em&gt;.config&lt;/em&gt; backup:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd /usr/src/linux&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cp /path/to/.config-backup .config &amp;amp;&amp;amp; chmod -x .config&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# make help&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# make silentoldconfig&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;If the &lt;em&gt;.config&lt;/em&gt; backup belongs to the same kernel version, we omit &lt;em&gt;make silentoldconfig&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;oldconfig&lt;/em&gt; asks for both new and old options.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;silentoldconfig&lt;/em&gt; only asks for NEW options while preserving old ones. Press ENTER to choose default setting.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;olddefconfig&lt;/em&gt; is similar but sets NEW options to default without confirmation.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;We might tune kernel options by graphical interface &lt;em&gt;make menuconfig&lt;/em&gt; below.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Menuconfig&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd /usr/src/linux&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# make menuconfig&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i915 e100e snd-hda-intel iTCO-wdt ahci i2c-i801 iwlwifi sdhci-pci&lt;/code&gt;.&lt;/p&gt;

        &lt;p&gt;Basic dirvers that needs activated.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IKCONFIG&lt;/code&gt; should be Y instead of M. This allows you to inspect (by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./scripts/extract-ikconfig /path/to/vmlinuz&lt;/code&gt;)the configuration of the kernel while it is running, without having to worry whether you&apos;ve changed or cleaned the source directory after it was built. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IKCONFIG_PROC&lt;/code&gt; stores kernel config at &lt;em&gt;/proc/config.gz&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NR_CPUS&lt;/code&gt; set to 4 since laptop has 2 cores and 4 threading. The smaller this value is, the smaller the kernel image is and the less memory is consumed by kernel.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MICROCDE&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MICROCDE_INTEL&lt;/code&gt; are Y by default. Refer to &lt;em&gt;microcode-ctl&lt;/em&gt; below.&lt;/li&gt;
      &lt;li&gt;Graphics. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i915&lt;/code&gt; = &lt;em&gt;Intel 8xx/9xx/G3x/G4x/HD Graphics, DRM_I915&lt;/em&gt; uses the default Y.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FB FRAMEBUFFER_CONSOLE X86_SYSFB FB_SIMPLE&lt;/code&gt; all set to Y.&lt;/p&gt;

        &lt;p&gt;Or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FB FRAMEBUFFER_CONSOLE FB_EFI&lt;/code&gt; to Y.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Ethernet. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e1000e&lt;/code&gt; = &lt;em&gt;Intel (R) PRO/1000 PCI-Express Gigabit Ethernet support&lt;/em&gt; set to M.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Audio. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snd_hda_intel&lt;/code&gt; = &lt;em&gt;Intel HD Audio, CONFIG_SND_HDA_INTEL&lt;/em&gt;. The default value is Y, now MUST be M. Choose the audio codec:&lt;/p&gt;

        &lt;p&gt;Refer to &lt;a href=&quot;https://forums.gentoo.org/viewtopic-t-791967-start-0.html&quot;&gt;no sound&lt;/a&gt; for how to decide the audio cdoec support.&lt;/p&gt;

        &lt;p&gt;Execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat /proc/asound/card0/codec#* \| grep -i codec&lt;/code&gt; in LiveDVD:&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Codec Conexant CX20590
Codec Intel CougarPoint HDMI
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;ol&gt;
          &lt;li&gt;Then select those two codecs as M. &lt;em&gt;Build HDMI/DisplayPort HD-audio codec support&lt;/em&gt; =&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; SND_HDA_CODEC_HDMI&lt;/code&gt;. &lt;em&gt;Conexant HD-audio support&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SND_HDA_CODEC_CONEXANT&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;&lt;em&gt;Enable generic HD-audio codec parser&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SND_HDA_GENERIC&lt;/code&gt; must be selected (default).&lt;/li&gt;
          &lt;li&gt;Set &lt;em&gt;Default time-out for HD-audio power-save mode&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_SND_HDA_POWER_SAVE_DEFAULT&lt;/code&gt; to 10.&lt;/li&gt;
          &lt;li&gt;Set &lt;em&gt;Pre-allocated buffer size for HD-audio driver&lt;/em&gt; to 4096.&lt;/li&gt;
          &lt;li&gt;You notice these options are ALL set to M! You can also set them all to Y. But never set some to M while set others to Y, othewise you would get no sound at all.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Webcamera
        &lt;ol&gt;
          &lt;li&gt;
            &lt;p&gt;lsusb&lt;/p&gt;

            &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 006: ID 04f2:b217 Chicony Electronics Co., Ltd Lenovo Integrated Camera (0.3MP)
Bus 001 Device 005: ID 0a5c:217f Broadcom Corp. BCM2045B (BDC-2.1)
Bus 001 Device 004: ID 147e:2016 Upek Biometric Touchchip/Touchstrip Fingerprint Sensor
Bus 001 Device 003: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;            &lt;/div&gt;

            &lt;p&gt;The 3rd item is the integrated webcamera which is a multimedia USB device.&lt;/p&gt;
          &lt;/li&gt;
          &lt;li&gt;
            &lt;p&gt;Enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MEDIA_SUPPORT&lt;/code&gt; = &lt;em&gt;Multimedia support&lt;/em&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MEDIA_CAMERA_SUPPORT&lt;/code&gt; = &lt;em&gt;Cameras/video grabbers support&lt;/em&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MEDIA_USB_SUPPORT&lt;/code&gt; = &lt;em&gt;Media USB Adapters&lt;/em&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB_VIDEO_CLASS&lt;/code&gt; = &lt;em&gt;USB Video Class (UVC)&lt;/em&gt;. The 2nd and 4th items are the key to make webcamera to work.&lt;/p&gt;
          &lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Processor type and features
        &lt;ol&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lscpu | grep -i &apos;CPU family&apos;&lt;/code&gt;. If the ouput is 6, select the 3rd item as &lt;em&gt;Core 2/newer Xeon&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_MCORE2&lt;/code&gt;, otherwise the output would be 15, please select the 5th item.&lt;/li&gt;
          &lt;li&gt;Turn off &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NUMA&lt;/code&gt; = &lt;em&gt;Numa Memory Allocation and Scheduler Support&lt;/em&gt;. Refer to &lt;a href=&quot;https://forums.gentoo.org/viewtopic-t-911696-view-next.html?sid=7c550d5e3f0942fbfcbc9ad80df53c57&quot;&gt;What Is NUMA?&lt;/a&gt;.&lt;/li&gt;
          &lt;li&gt;Remove several &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AMD&lt;/code&gt; items under &lt;em&gt;Processor type and features&lt;/em&gt; by searching AMD. They are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AGP_AMD64 X86_MCE_AMD MICROCODE_AMD AMD_NUMA AMD_IOMMU&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;Enable &lt;em&gt;EFI runtime service support&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EFI&lt;/code&gt; if UEFI is used to boot the system. Turn off &lt;em&gt;EFI stub support&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EFI_STUB&lt;/code&gt;, &lt;em&gt;EFI mixed-mode support&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EFI_MIXED&lt;/code&gt;, &lt;em&gt;Built-in kernel command line&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMDLINE_BOOL&lt;/code&gt;, &lt;em&gt;Built-in kernel command string&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_CMDLINE&lt;/code&gt; and &lt;em&gt;Initramfs source file(s)&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INITRAMFS_SOURCE&lt;/code&gt;. These options are closely related mainly for compiling kernel boot arguments and &lt;em&gt;initramfs&lt;/em&gt; into kernel image. Then the system can boot and load kernel directly from EFI firmware instead of bootloader. Details refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/EFI_stub_kerne&quot;&gt;efi stub kernel&lt;/a&gt;.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INPUT_PCSPKR&lt;/code&gt; as M or Y for the standard PC Speaker to be used for bells and whistles. Don&apos;t enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SND_PCSP&lt;/code&gt; (read the kernel help message)!&lt;/li&gt;
      &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X86_X32&lt;/code&gt; = &lt;em&gt;x32 ABI for 64-bit mode&lt;/em&gt; to Y. This option is useful for 32 bit binaries to take advantage of the system 64-bit registers.&lt;/li&gt;
      &lt;li&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IOMMU_SUPPORT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INTEL_IOMMU&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INTEL_IOMMU_DEFAULT_ON&lt;/code&gt; set to N since laptop lacks VT-d (but has VT-x). VT-d is what Intel calls their IOMMU implementation. Refer to &lt;a href=&quot;http://ark.intel.com/products/52224/Intel-Core-i5-2410M-Processor-3M-Cache-up-to-2_90-GHz&quot;&gt;i5 2410M&lt;/a&gt;. Without IOMMU enabled, HD3000 graphics will tear and corrupt.&lt;/li&gt;
      &lt;li&gt;Watchdog. &lt;em&gt;Intel TCO Timer/Watchdog&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITCO_WDT&lt;/code&gt; set  to M.&lt;/li&gt;
      &lt;li&gt;SATA. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ahci&lt;/code&gt; = &lt;em&gt;AHCI SATA support&lt;/em&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SATA_AHCI&lt;/code&gt; for SATA disks selected &apos;Y&apos; default. Disable &lt;em&gt;ATA SFF support (for legacy IDE and PATA)&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ATA_SFF&lt;/code&gt; set to N.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;Intel 82801 (ICH/PCH)&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;I2C_I801&lt;/code&gt; uses default &apos;Y&apos;.&lt;/li&gt;
      &lt;li&gt;Wireless. &lt;em&gt;Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi), CONFIG_IWLWIFI&lt;/em&gt; set to M. By the way, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant&lt;/code&gt; needs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nl80211&lt;/code&gt; wifi driver. Actually relates to &lt;em&gt;cfg80211 - wireless configuration API&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CFG80211&lt;/code&gt; which is set to Y default already.&lt;/li&gt;
      &lt;li&gt;(opt) Bluetooth. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BT&lt;/code&gt; = &lt;em&gt;Bluetooth subsystem support&lt;/em&gt; to M. Enter and find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BT_RFCOMM&lt;/code&gt; = &lt;em&gt;RFCOMM protocol support&lt;/em&gt;. I think this should be &apos;M&apos;, otherwise package like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obexfs&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obexftp&lt;/code&gt; did not work. Choose USB driver &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BT_HCIBTUSB&lt;/code&gt; = &lt;em&gt;HCI USB driver&lt;/em&gt; as M. The sub-option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BT_HCIBTUSB_BCM&lt;/code&gt; turned on automatically. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BT_HIDP&lt;/code&gt; = &lt;em&gt;HIDP protocol support&lt;/em&gt; is for human interface device like bluetooth mouse, bluetooth headset, bluetooth keyboard etc. Since I dont&apos; use them, so leave it as N. My bluetooth &lt;em&gt;Logitech mouse&lt;/em&gt; works perfectly even when turnning off all the related bluetooth kernel options. That is due to the extra &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOGITECH&lt;/code&gt; related kernel drivers. Read more from &lt;em&gt;bluetooth - bluez obexfs&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;MMC. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdhci_pci&lt;/code&gt; = &lt;em&gt;SDHCI support on PCI bus&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MMC_SDHCI_PCI&lt;/code&gt;, but you cannot positioninig the item since its parent &lt;em&gt;Secure Digital Host Controller Interface Support&lt;/em&gt; is turned off by default. So turn this on first. By the way, set &lt;em&gt;Ricoh MMC Controller Disabler&lt;/em&gt; = MMC_RICOH_MMC` as Y.&lt;/li&gt;
      &lt;li&gt;Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/Xorg/Configuration#Installing_Xorg&quot;&gt;Xorg configruation&lt;/a&gt; to enable Xorg kernel support. However, according to this reference, nothing needs updated.&lt;/li&gt;
      &lt;li&gt;NTFS. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NTFS_FS&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FUSE_FS&lt;/code&gt; to M. Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/NTFS&quot;&gt;NTFS wiki&lt;/a&gt;. You need to install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ntfs-3g&lt;/code&gt; package later on. Since &lt;em&gt;ntfs-3g&lt;/em&gt; embeds NTFS write, set&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NTFS_RW&lt;/code&gt; to N.&lt;/li&gt;
      &lt;li&gt;Turn on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PACKET&lt;/code&gt; (default Y)  for wireless tool &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wpa_supplicant&lt;/code&gt; which will be installed later on.&lt;/li&gt;
      &lt;li&gt;Turn off &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NET_VENDOR_NVIDIA&lt;/code&gt; since no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NVIDIA&lt;/code&gt; card in laptop.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAT_DEFAULT_CODEPAGE&lt;/code&gt; to 936 (without prefix &lt;em&gt;cp&lt;/em&gt;), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAT_DEFAULT_IOCHARSET&lt;/code&gt; uses default &lt;em&gt;iso8859-1&lt;/em&gt; (this value should include the prefix &lt;em&gt;cp&lt;/em&gt; such as &lt;em&gt;cp936&lt;/em&gt;) but turn on it&apos;s sub-option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAT_DEFAULT_UTF8&lt;/code&gt;.&lt;/p&gt;

        &lt;p&gt;Enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NLS_CODEPAGE_936&lt;/code&gt; to Y or M. Current &lt;em&gt;initramfs&lt;/em&gt; reads LUKS key from VFAT USB partition on boot, MUST set to be Y, otherwise it would fail to find (mount) the key device.&lt;/p&gt;

        &lt;p&gt;Turn off &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NLS_CODEPAGE_437&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NLS_ASCII&lt;/code&gt; since we either use UTF-8 or GBK system. Keep &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NLS_ISO8859_1&lt;/code&gt; since it&apos;s the default value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAT_DEFAULT_IOCHARSET&lt;/code&gt;.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Dm-crypt. &lt;em&gt;Device mapper support&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLK_DEV_DM&lt;/code&gt; is set Y by default. &lt;em&gt;Crypt target support&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DM_CRYPT&lt;/code&gt; must be M or Y. &lt;em&gt;XTS support&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CRYPTO_XTS&lt;/code&gt; and &lt;em&gt;AES cipher algorithms (x86_64)&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CRYPTO_AES_X86_64&lt;/code&gt; optionally set to M (recommended). Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/Dm-crypt&quot;&gt;Dm-crypt&lt;/a&gt;. Refer to &lt;em&gt;Cryptsetup&lt;/em&gt; step below. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CRYPTO_SERPENT&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CRYPTO_SHA512&lt;/code&gt; must be Y instead of M if relevant LUKS algorithms are used. Refer to &lt;a href=&quot;2015/08/15/gentoo-over-lvm-luks/&quot;&gt;gentoo over lvm luks&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;Iptables. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NETFILTER_ADVANCED&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XT_MATCH_OWNER&lt;/code&gt; (&lt;em&gt;-m owner&lt;/em&gt;). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP_NF_TARGET_REDIRECT&lt;/code&gt; (-j REDIRECT) which will enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NF_NAT_REDIRECT&lt;/code&gt; (in return, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NETFILTER_XT_TARGET_REDIRECT&lt;/code&gt; be enabled as well). We only need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NETFILTER_XT_TARGET_REDIRECT&lt;/code&gt; for iptables REDIRECT, so to simplify kernel, just enable it alone. If necessary, turn on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP6_NF_NAT&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NF_NAT_IPV6&lt;/code&gt; as dependency) to enable ip6tables &lt;em&gt;nat&lt;/em&gt; table. Turn on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NETFILTER_XT_MATCH_MULTIPORT&lt;/code&gt; for &lt;em&gt;-m multiport&lt;/em&gt;. Turn on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_NETFILTER_XT_TARGET_TPROXY&lt;/code&gt; for &lt;em&gt;-j TPROXY&lt;/em&gt; target support.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;System log: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SECURITY_DMESG_RESTRICT&lt;/code&gt; to Y. Refer to &lt;a href=&quot;https://lwn.net/Articles/414813/&quot;&gt;Restrict unprivileged access to kernel syslog&lt;/a&gt;.&lt;/p&gt;

        &lt;p&gt;More refer to &lt;em&gt;syslog-ng&lt;/em&gt; below.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Filesystem. Set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UDF_FS&lt;/code&gt; as M to mount ISO file.&lt;/li&gt;
      &lt;li&gt;SquashFS. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_SQUASHFS&lt;/code&gt; as M; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_SQUASHFS_XATTR&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_SQUASHFS_XZ&lt;/code&gt; as Y. (&lt;em&gt;sys-fs/squashfs-tools&lt;/em&gt;).&lt;/li&gt;
      &lt;li&gt;IO scheduler - BFQ: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IOSCHED_BFQ&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLK_CGROUP&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BFQ_GROUP_IOSCHED&lt;/code&gt; as Y.&lt;/li&gt;
      &lt;li&gt;Magic SysRq key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_MAGIC_SYSRQ&lt;/code&gt; as Y. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE&lt;/code&gt; configure default value of &lt;em&gt;/proc/sys/kernel/sysrq&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/User:Maffblaster/Drafts/WireGuard&quot;&gt;WireGuard&lt;/a&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NET_FOU&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NET_UDP_TUNNEL&lt;/code&gt;) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PADATA&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;IP set: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP_SET&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP_SET_HASH_IP&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP_SET_HASH_NET&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IP_SET_LIST_SET&lt;/code&gt;; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NETFILTER_XT_SET&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NETFILTER_XT_MARK&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;(opt) Thinkpad-related. &lt;em&gt;ThinkPad ACPI Laptop Extras&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;THINKPAD_ACPI&lt;/code&gt; set to M.&lt;/li&gt;
      &lt;li&gt;[e-sources / cjktty patch specific options].&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FONTS&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FONT_8x16&lt;/code&gt; set to Y. And &lt;em&gt;console 16x16 CJK font ( cover BMP )&lt;/em&gt; = &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FONT_16x16_CJK&lt;/code&gt; which is &lt;em&gt;cjktty&lt;/em&gt; patch. These options are for Chinese characters display in TTY (Ctrl + Alt + Fn).&lt;/li&gt;
      &lt;li&gt;Reference links: &lt;a href=&quot;http://www.jinbuguo.com/kernel/longterm-3_10-options.html&quot;&gt;Linux-3.10-x86_64 内核配置选项简介&lt;/a&gt;; &lt;a href=&quot;http://www.kroah.com/lkn/&quot;&gt;Linux Kernel in a Nutshell&lt;/a&gt;; &lt;a href=&quot;http://kernel-seeds.org/&quot;&gt;kernel-seeds&lt;/a&gt;; &lt;a href=&quot;http://kmuto.jp/debian/hcl&quot;&gt;device driver check page&lt;/a&gt;; &lt;a href=&quot;http://unix.stackexchange.com/a/97813&quot;&gt;How do you get hardware info and select drivers to be kept in a kernel compiled from source&lt;/a&gt;; and &lt;a href=&quot;http://kernel-seeds.org/working.html&quot;&gt;Working with Kernel Seeds&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Compiling&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cd /usr/src/linux&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount /dev/sda10 /boot; mount /dev/sda2 /boot/efi&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# make clean/mrproper/distclean; echo 3 &amp;gt; /proc/sys/vm/drop_caches&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# make modules_prepare&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# make -j3 &amp;amp;&amp;amp; make modules_install &amp;amp;&amp;amp; make install&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# genkernel --install initramfs&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# grub-mkconfig -o /boot/grub/grub.cfg&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt @module-rebuild&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# reboot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Make sure we are in kernel sources directory.&lt;/li&gt;
      &lt;li&gt;This is usually done before chrooting.&lt;/li&gt;
      &lt;li&gt;Clean previous building leftovers.
        &lt;ol&gt;
          &lt;li&gt;&lt;em&gt;clean&lt;/em&gt; removes most generated files but keep the &lt;em&gt;.config&lt;/em&gt; and enough build support to build external modules (such that we overlook &lt;em&gt;make modules_prepare&lt;/em&gt;).&lt;/li&gt;
          &lt;li&gt;&lt;em&gt;mrproper&lt;/em&gt; removes all generated files + &lt;em&gt;.config&lt;/em&gt; + various backup files.&lt;/li&gt;
          &lt;li&gt;&lt;em&gt;distclean&lt;/em&gt; = &lt;em&gt;mrproper&lt;/em&gt; + remove editor backup and patch files.&lt;/li&gt;
          &lt;li&gt;&lt;em&gt;drop_caches&lt;/em&gt; is set to 3.&lt;/li&gt;
        &lt;/ol&gt;

        &lt;p&gt;They are chosen if we re-compile kernel sources in case of compiling error. What&apos;s worse, a successful re-compiling generates unworkable kernel binaries.&lt;/p&gt;

        &lt;p&gt;Please be noted that &lt;em&gt;mrproper&lt;/em&gt; and &lt;em&gt;disclean&lt;/em&gt; will remove backup files, especially the &lt;em&gt;.config&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;em&gt;make modules_prepare&lt;/em&gt; is somewhat complicated.&lt;/p&gt;

        &lt;p&gt;External kernel modules (i.e. self-written codes; VirtualBox binary kernel modules) are built against kernel tree (&lt;em&gt;/usr/src/linux/&lt;/em&gt;). That&apos;s because external modules building need support from kernel sources support (i.e. kernel sources&apos; head file).&lt;/p&gt;

        &lt;p&gt;So the kernel tree should be prepared to support external kernel modules building, which can be achieve by several ways:&lt;/p&gt;

        &lt;ol&gt;
          &lt;li&gt;If the kernel tree is brand new (i.e. just unpacked) and we will build external kernel modules before kernel building, we should prepare by &lt;em&gt;make modules_prepare&lt;/em&gt; under &lt;em&gt;/usr/src/linux/&lt;/em&gt;.&lt;/li&gt;
          &lt;li&gt;If the kernel have already been built (i.e. &lt;em&gt;make -j3&lt;/em&gt;), it&apos;s already prepared. Need to prepare.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Compiling.
        &lt;ol&gt;
          &lt;li&gt;Compiles the kernel. Keep &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-j3&lt;/code&gt; since MAKEOPTS in &lt;em&gt;make.conf&lt;/em&gt; does not apply to kernel compiling.&lt;/li&gt;
          &lt;li&gt;Install kernel modules into &lt;em&gt;/lib/modules/`uname -r`&lt;/em&gt;. If we are re-compiling the kernel, old modules will be overriden. Ether backup the old modules or install modules to a new location (by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSTALL_MOD_PATH&lt;/code&gt;) when we want the old kernel be bootable (i.e. we remove a module from kernel).&lt;/li&gt;
          &lt;li&gt;Install kernel binaries &lt;em&gt;System.map, config, initramfs, vmlinuz&lt;/em&gt; into &lt;em&gt;/boot&lt;/em&gt; and rename old identical version kernel binaries on demand. We can copy and even rename those binaries manually as long as filenames are kept consistent.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;For LVM/LUKS containers, emerge &lt;em&gt;genkernel&lt;/em&gt; with &lt;em&gt;cryptsetup&lt;/em&gt; USE.&lt;/p&gt;

        &lt;p&gt;Extra arguments &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--lvm --luks --gpg --busybox&lt;/code&gt; should be supplied upon generates &lt;em&gt;initramfs&lt;/em&gt;. Refer to &lt;a href=&quot;/2015/08/15/gentoo-over-lvm-luks/&quot;&gt;Gentoo rootfs over LVM encrypted in LUKS container&lt;/a&gt; and &lt;a href=&quot;/2015/09/10/lvm-luks-lvm/&quot;&gt;lvm luks lvm&lt;/a&gt;.&lt;/p&gt;

        &lt;p&gt;Like modules, &lt;em&gt;genkernel&lt;/em&gt; does not backup &lt;em&gt;initramfs&lt;/em&gt; automatically when re-compiling the kernel. We are responsible for bakcuping manually, especially when the &lt;em&gt;genkernel&lt;/em&gt; arguments are different.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Append current kernel to Grub menu.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Although we are on the old kernel, &lt;em&gt;@module-rebuild&lt;/em&gt; knows how to re-install external kernel modules for the new kernel as long as &lt;em&gt;/usr/src/linux&lt;/em&gt; symlink pointing the new kernel source tree (see &lt;em&gt;eselect kernel list&lt;/em&gt;).&lt;/p&gt;

        &lt;p&gt;Optionally, this step could be omitted if we are re-compiling the kernel, or we have done &lt;em&gt;make modules_prepare&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Linux firmware&lt;/p&gt;

    &lt;p&gt;Some drivers require additional firmware to be installed on the system before they work. This is often the case for network interfaces, especially wireless network interfaces.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt --fechonly sys-kernel/linux-firmware&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Firstly just fetch the package sources. If network failed connect after booting into new kernel, emerge it then.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;system-configuration&quot;&gt;System configuration&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;fstab&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;Creating the &lt;em&gt;/etc/fstab&lt;/em&gt; file. Use backup at best. The default &lt;em&gt;/etc/fstab&lt;/em&gt; file provided by Gentoo is not a valid fstab file but instead more of a template.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/dev/sda10   /boot		ext2    defaults,noatime	1 2
/dev/sda12   /   		ext4    noatime	       0 1
/dev/sda7    none	  	swap	sw	       0 0
proc         /proc          proc    nosuid,nodev,noexec,hidepid=2,gid=wheel 0 0
none         /tmp           tmpfs   nodev,nosuid,noexec     0 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Double-check the &lt;em&gt;/etc/fstab&lt;/em&gt; file, save and quit to continue. Fault &lt;em&gt;fstab&lt;/em&gt; results in boot failure.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;hostname&lt;/em&gt; and &lt;em&gt;domain&lt;/em&gt;
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;nano -w &lt;em&gt;/etc/conf.d/hostname&lt;/em&gt;&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;hostname=&quot;myhost&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;On login, usually get message like &lt;em&gt;This is myhost.unkown_domain …&lt;/em&gt; which is not a error, but annoying. There are two ways to get rid of it.&lt;/p&gt;

        &lt;p&gt;The first way is to set a fake domain for localhost, edit &lt;em&gt;/etc/hosts&lt;/em&gt;. Add fake &lt;em&gt;hostname.domain&lt;/em&gt; to &lt;em&gt;localhost&lt;/em&gt;.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# &amp;lt;ip address&amp;gt;	&amp;lt;fully qualified hostname&amp;gt;	&amp;lt;aliases&amp;gt;
127.0.0.1       myhost.jiantu.boxes      myhost   localhost
::1             myhost.jiantu.boxes      myhost   localhost
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;Now try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ping myhost.jiantu.boxes/myhost/localhost&lt;/code&gt; to test.&lt;/p&gt;

        &lt;p&gt;Another method is edit &lt;em&gt;/etc/issue&lt;/em&gt;, remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.\O&lt;/code&gt;.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable OpenRC log&lt;/p&gt;

    &lt;p&gt;Edit &lt;em&gt;/etc/rc.conf&lt;/em&gt; and set &lt;em&gt;rc_logger=&quot;YES&quot;&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Set root password&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# passwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;networking&quot;&gt;&lt;a href=&quot;/2016/03/01/networking/&quot;&gt;Networking&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;dhcpcd&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;We don&apos;t follow &lt;a href=&quot;https://wiki.gentoo.org/wiki/Handbook:AMD64&quot;&gt;Handbook&lt;/a&gt;&apos;s &lt;em&gt;net config&lt;/em&gt;. &lt;em&gt;net-misc/netifrc&lt;/em&gt; requires support from DHCP, while &lt;em&gt;net-misc/dhcpcd&lt;/em&gt; can handle network configuration alone.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt net-misc/dhcpcd&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-update add dhcpcd default&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt net-wireless/wpa_supplicant&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Personal DNS servers can be put into &lt;em&gt;/etc/resolv.conf.head&lt;/em&gt; and/or &lt;em&gt;/etc/resolv.conf.tail&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;In case of the network interface card should be configured with a static IP address, entries can also be manually added to &lt;em&gt;/etc/dhcpcd.conf&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;If need GUI tool, use NetworkManager instead of &lt;em&gt;wicd&lt;/em&gt; since the later one don&apos;t support &lt;em&gt;nl80211&lt;/em&gt; driver. Also Networkmanager depends on &lt;em&gt;wpa_supplicant&lt;/em&gt; and &lt;em&gt;dhcpcd&lt;/em&gt; or &lt;em&gt;dhcpclient&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Reference: &lt;a href=&quot;https://wiki.gentoo.org/wiki/Network_management_using_DHCPCD&quot;&gt;Network management using DHCPCD&lt;/a&gt;; &lt;a href=&quot;https://wiki.gentoo.org/wiki/Wpa_supplicant&quot;&gt;wpa_supplicant&lt;/a&gt;; &lt;a href=&quot;https://wiki.gentoo.org/wiki/Handbook:AMD64/Networking/Wireless&quot;&gt;Handbook:AMD64/Networking/Wireless&lt;/a&gt;; &lt;a href=&quot;http://w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf&quot;&gt;configuration example&lt;/a&gt;; &lt;a href=&quot;http://blog.ust.hk/yang/2012/09/21/wpa_supplicant-conf-for-smobilenet-in-hkust/&quot;&gt;wpa_supplicant.conf for sMobileNet in HKUST&lt;/a&gt;; &lt;a href=&quot;http://www.freebsd.org/cgi/man.cgi?wpa_supplicant.conf&quot;&gt;wpa_supplicant.conf&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;wpa_supplicant&lt;/em&gt;&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;dhcpcd&lt;/em&gt; manages Ethernet connection on boot while revoking &lt;em&gt;wpa_supplicant&lt;/em&gt; hook script to initiate wireless networking.&lt;/li&gt;
      &lt;li&gt;Remove the recommended options  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GROUP=wheel&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update_config=1&lt;/code&gt; from Wiki for security reason.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;&lt;em&gt;/etc/wpa_supplicant/wpa_supplicant.conf&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ctrl_interface=DIR=/var/run/wpa_supplicant
ctrl_interface_group=0
fast_reauth=1
eapol_version=1
ap_scan=1

network={
        disabled=0
        ssid=&quot;public-wifi&quot;
        key_mgmt=NONE
        priority=-999
}

network={
        disabled=1
        ssid=&quot;Network1&quot;
        proto=WPA RSN
        key_mgmt=WPA-EAP
        pairwise=CCMP TKIP
        group=CCMP TKIP 
        eap=PEAP
        identity=&quot;XXXXXXXX&quot;
        password=&quot;YYYYYYYY&quot;
        ca_cert=&quot;/etc/ssl/certs/Thawte_Premium_Server_CA.pem&quot;
        phase1=&quot;peaplabel=0&quot;
        phase2=&quot;auth=MSCHAPV2&quot;
        priority=10
}

network={
        disabled=1
        ssid=&quot;Network2&quot;
        proto=WPA RSN
        key_mgmt=WPA-EAP
        pairwise=CCMP TKIP
        group=CCMP TKIP 
        eap=PEAP
        identity=&quot;XXXXXXXX&quot;
        password=&quot;YYYYYYYY&quot;
# Don&apos;t need certificate
#       ca_cert=&quot;/etc/ssl/certs/Thawte_Premium_Server_CA.pem&quot;
# If use the latest wpa_supplicant, try &apos;tls_disable_tls_v1_2=1&apos;
#       phase1=&quot;tls_disable_tlsv1_2=1&quot;
        phase1=&quot;peaplabel=0&quot;
        phase2=&quot;auth=MSCHAPV2&quot;
        priority=20
}

network={
        disabled=0
        ssid=&quot;Network3&quot;
        #psk=&quot;12345678&quot;
        psk=aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbccccccccccccccccccc
        priority=30
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;For home wireless connection, usuaully you just need to specify &lt;em&gt;ssid&lt;/em&gt; and &lt;em&gt;psk&lt;/em&gt; arguments. &lt;em&gt;psk&lt;/em&gt; can be a normal wifi password (call &lt;em&gt;passphrase&lt;/em&gt;) or a 256-character string. When use normal password, need quotes, while 256-character string does not. How to generate the long string?&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# wpa_passphrase wifi-ssid wifi-password &amp;gt;&amp;gt; /etc/wpa_supplicant/wpa_supplicant.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;We&apos;d better change the permissions to ensure that WiFi passwords can not be viewed in &lt;em&gt;psk&lt;/em&gt; or &lt;em&gt;passphrase&lt;/em&gt; by normal user account.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf`.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;dhcpcd&lt;/em&gt; invokes &lt;em&gt;wpa_supplicant&lt;/em&gt; through &lt;em&gt;/lib/dhcpcd/dhcpcd-hooks/10-wpa_supplicant&lt;/em&gt; hook. From &lt;em&gt;dhcpcd-6.10.0&lt;/em&gt; onward, &lt;em&gt;10-wpa_supplicant&lt;/em&gt; hook is no longer there by default. We should copy &lt;em&gt;/usr/share/dhcpcd/hooks/10-wpa_supplicant&lt;/em&gt; to &lt;em&gt;/lib/dhcpcd/dhcpcd-hooks/10-wpa_supplicant&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lspci -k&lt;/code&gt; shows wireless driver in use is &lt;em&gt;iwlwifi&lt;/em&gt;. However if specify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-D iwlwifi&lt;/code&gt; on command line, &lt;em&gt;wpa_supplicant&lt;/em&gt; will fail:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;Unsupported driver &apos;iwlwifi&apos;&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;The actual driver in use was &lt;em&gt;nl80211&lt;/em&gt;.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;If you have installed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;net-misc/netifrc&lt;/code&gt; (by default from &lt;em&gt;stage3&lt;/em&gt;) and created &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/ini.d/net.*&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/conf.d/net&lt;/code&gt; files, refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/Network_management_using_DHCPCD#Migration_from_Gentoo_net..2A_scripts&quot;&gt;Migration from Gentoo net.* scripts&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;wpa_supplicant-2.4&lt;/em&gt; might cause authentication problem for PEAP Wifi. Refer to &lt;a href=&quot;/2015/05/11/gentoo-downgrade-package/&quot;&gt;Downgrade Package &amp;amp;&amp;amp; wpa_supplicant &amp;amp;&amp;amp; local overlay&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;system-tools&quot;&gt;System tools&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Portage tools&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt eix; eix-update&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt gentoolkit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;System logger.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt app-admin/syslog-ng app-admin/logrotate&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-update add syslog-ng default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;By default, there is a line&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;log { source(src); destination(console_all); };
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;in &lt;em&gt;/etc/syslog-ng/syslog-ng.conf&lt;/em&gt;, which outputs system logs to &lt;em&gt;/dev/tty12&lt;/em&gt;. That&apos;s to say, any users can read system logs by switching to the 12th virtual terminal. For security reason, comment out that line if there are multiple users.&lt;/p&gt;

    &lt;p&gt;Details on logrotate for cron jobs refer to &lt;a href=&quot;/2015/07/19/cronie/&quot;&gt;Cronie and Anacron&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Cron daemon&lt;/p&gt;

    &lt;p&gt;A cron daemon executes scheduled commands. It is very handy if some command needs to be executed regularly (for instance daily, weekly or monthly).&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;sys-process/cronie anacron&quot; &amp;gt; /etc/portage/package.use/cronie (opt)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt sys-process/cronie&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-update add cronie default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;anaron&lt;/em&gt; USE is not must if no rigid shechuled tasks.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;cronie&lt;/em&gt; must be in a runlevel to shedule &lt;em&gt;logrotate&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Details on running scheduled tasks based on input from the command &lt;em&gt;crontab&lt;/em&gt;, refer to &lt;a href=&quot;/2015/07/19/cronie/&quot;&gt;Cronie and Anacron&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;More&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt sys-apps/mlocate, file indexing&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt sys-fs/ntfs3g, mounting NTFS filesystem&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-update add sshd default, incoming SSH connection (opt)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;bootloader---grub2&quot;&gt;Bootloader - &lt;a href=&quot;https://wiki.gentoo.org/wiki/GRUB2&quot;&gt;Grub2&lt;/a&gt;&lt;/h1&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &apos;GRUB_PLATFORMS=&quot;efi-64&quot;&apos; &amp;gt;&amp;gt; /etc/portage/make.conf&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt grub:2 os-prober&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount /dev/sda10 /boot; mount /dev/sda2 /boot/efi&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# grub-install --target=x86_64-efi [--bootloader-id=Gentoo_Grub] [--efi-directory=esp] [--removable] [/dev/sda]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;This must be the 1st step. Otherwise it would show &lt;em&gt;error: /usr/lib/grub/x86_64-efi/modinfo.sh doesn&apos;t exist&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Default to slot 2. If there are other operating system (i.e. dual boot), &lt;em&gt;os-prober&lt;/em&gt; is suggested.&lt;/li&gt;
  &lt;li&gt;Make sure &lt;em&gt;boot&lt;/em&gt; and EFI partition are mounted. Because Gentoo, Ubuntu, Windows share the EFI partition, we mount the shared EFI partion here.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;a-bit-of-explanation&quot;&gt;A bit of explanation&lt;/h2&gt;

&lt;p&gt;By default, EFI partition is mounted at &lt;em&gt;/boot/efi&lt;/em&gt;. Actually, we can mount it anywhere as long as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--efi-directory&lt;/code&gt; is correctly set.&lt;/p&gt;

&lt;p&gt;Install the GRUB UEFI application &lt;em&gt;grubx64.efi&lt;/em&gt; to &lt;em&gt;esp/EFI/Gentoo_Grub/&lt;/em&gt; and install Grub modules to &lt;em&gt;/boot/grub/x86_64-efi/&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Chceck &lt;a href=&quot;https://wiki.archlinux.org/index.php/GRUB/EFI_examples#X270_Thinkpad&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--removable&lt;/code&gt;&lt;/a&gt; argument, without which the booting entry would not show up in UEFI NVRAM list within BIOS setting. You will find &lt;em&gt;esp/EFI/BOOT/BOOTX64.EFI&lt;/em&gt; is just a copy of &lt;em&gt;esp/EFI/Gentoo_Grub/grub64.efi&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You&apos;d better set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSTALL_DEVICE&lt;/code&gt; when there exists multiple disks and/or multiple EFI partitions in case of ambiguity.&lt;/p&gt;

&lt;h2 id=&quot;deprecated-manually-grub-menu&quot;&gt;[deprecated] Manually Grub menu&lt;/h2&gt;

&lt;p&gt;As long as the &lt;em&gt;/boot&lt;/em&gt; and &lt;em&gt;/boot/efi&lt;/em&gt; partitions are mounted, &lt;em&gt;grub-mkconfig&lt;/em&gt; automatically detects other operating systems and writes to &lt;em&gt;/etc/grub.d/30_os_prober&lt;/em&gt; through &lt;em&gt;sys-boot/os-prober&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Chainloading Windows system manully in &lt;em&gt;/etc/grub.d/40_custom&lt;/em&gt;. The traditional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chainloader +1&lt;/code&gt; does not boot Windows based on UEFI.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;menuentry &quot;Microsoft Windows 8.1 x86_64&quot; {
    insmod part_gpt
    insmod fat
    insmod search_fs_uuid
    insmod chain
    search --fs-uuid --no-floppy --set=root $hints_string $fs_uuid
    chainloader /efi/Microsoft/Boot/bootmgfw.efi
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The next is to replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$hints_string&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$fs_uuid&lt;/code&gt;. This is where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;os-prober&lt;/code&gt; comes into playing a role.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# grub-probe --target=hints\_string /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi
# grub-probe --target=fs\_uuid /boot/efi/EFI/Microsoft/Boot/bootmgfw.efi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Print &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$hints_string&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Print &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fs_uuid&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Now replace the relevant values.&lt;/li&gt;
  &lt;li&gt;Refer to &lt;a href=&quot;https://wiki.archlinux.org/index.php/GRUB\#Windows_installed_in_UEFI-GPT_Mode_menu_entry&quot;&gt;Windows installed in UEFI-GPT Mode menu entry&lt;/a&gt; and &lt;a href=&quot;http://unix.stackexchange.com/q/49165&quot;&gt;Can GRUB2 share the EFI system partition with Windows?&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;generate-grub-menu&quot;&gt;Generate grub menu&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# grub-mkconfig -o /boot/grub/grub.cfg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;get-out-of-chroot---reboot&quot;&gt;Get out of Chroot - Reboot&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Exit the chrooted environment: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exit&lt;/code&gt; and unmount all mounted partitions:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# exit
# umount -lv /mnt/gentoo/home
# umount -lv /mnt/gentoo/boot{/efi,}
# umount -lv /mnt/gentoo/dev{/shm,/pts,}
# umount -lv /mnt/gentoo{/proc,/sys,}
# reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;When rebooting, if the LiveDVD usb stick is still plugged onto the computer, the chainload to Ubuntu grub does not work. You find &lt;em&gt;error: disk hd0,gpt2 not found&lt;/em&gt;. This is because Grub treats the USB stick as &lt;em&gt;hd0&lt;/em&gt; while the hard disk as &lt;em&gt;hd1&lt;/em&gt;. You can unplug the USB, and CTRL+ALT+DEL. Another way is to edit the Grub menu from &lt;em&gt;hd0&lt;/em&gt; to &lt;em&gt;hd1&lt;/em&gt;, then press F10 to boot.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;finalizing&quot;&gt;Finalizing&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;User&lt;/p&gt;

    &lt;p&gt;The very first thing after getis to create a regular user account:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# check all accounts&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# passwd &lt;span class=&quot;nt&quot;&gt;-Sa&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# create a new one&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# useradd &lt;span class=&quot;nt&quot;&gt;-G&lt;/span&gt; wheel,video &lt;span class=&quot;nt&quot;&gt;-ms&lt;/span&gt; /bin/bash &amp;lt;username&amp;gt;
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;root@host ~]# passwd &amp;lt;username
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Compared to &lt;em&gt;useradd&lt;/em&gt;, &lt;em&gt;adduser&lt;/em&gt; has a nice interactive mode.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Check wireless network.&lt;/p&gt;

    &lt;p&gt;If fail to connect,&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt linux-firmware&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Remember we have fetched the package sources.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;system-upate&quot;&gt;System upate&lt;/h1&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# eix-sync&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avtuDN --with-bdeps=y @world&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# dispatch-conf (opt)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# revdep-rebuild -pv (opt)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt @preserved-rebuild&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -av --depclean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;For &lt;em&gt;&amp;gt;=portageq-2.2.16&lt;/em&gt;, &lt;em&gt;emaint sync&lt;/em&gt; replaces original &lt;em&gt;emerge –sync&lt;/em&gt; to sync Portage tree.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;–with-bdeps=y&lt;/em&gt; will calculate build time dependencies for updates. Append this argument occasionally.&lt;/li&gt;
  &lt;li&gt;If configuration needs updated, there will be a corresponding &lt;em&gt;._cfg*&lt;/em&gt; file.&lt;/li&gt;
  &lt;li&gt;As a tool of &lt;em&gt;gentoolkit&lt;/em&gt;, &lt;em&gt;revdep-rebuild&lt;/em&gt; is Gentoo&apos;s Reverse Dependency rebuilder. It will scan the installed ebuilds to find broken packages as a result of an upgrade of their dependencies. Those packages will be re-merged. However, it can also happen that a given package does not work with the currently upgraded dependencies, in which case you should upgrade the broken package to a more recent version. &lt;em&gt;revdep-rebuild&lt;/em&gt; will pass flags to emerge which lets you use the –pretend flag to see what is going to be emerged again before going any further.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emerge --info \| grep FEATURES&lt;/code&gt; prints &lt;em&gt;preserve-libs&lt;/em&gt; FEATURE is enabledby default. It tells Portage to preserve libraries when &lt;em&gt;soname&lt;/em&gt;&apos;s change during upgrade or downgrade, only as necessary to satisfy shared library dependencies of installed consumers/packages. Preserved libraries are automatically removed when there are no remaining consumers, which occurs when consumer packages are rebuilt or uninstalled. Ideally, rebuilds are triggered automatically during updates, in order to satisfy slot-operator dependencies.&lt;/p&gt;

    &lt;p&gt;However, before emerge exits during installing updates, if there are remaining preserved libraries because slot-operator dependencies have not been used to trigger automatic rebuilds, then emerge will display a message:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;!!! existing preserved libs:
&amp;gt;&amp;gt;&amp;gt; package: sys-libs/libfoo-1
 * - /lib/libfoo.so.1
 *      used by /usr/bin/bar (app-foo/bar-1)
Use emerge @preserved-rebuild to rebuild packages using these libraries
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Clean packages out of dependency tree.&lt;/p&gt;

    &lt;p&gt;Cleans the system by removing packages that are  not  associated with  explicitly merged packages. Depclean works by creating the full dependency tree from the @world set, then comparing it to installed packages. Packages installed, but not part of the dependency tree, will be uninstalled by depclean.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;depclean&lt;/em&gt; is the last stage of system update.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;chroot---a-complete-routine&quot;&gt;Chroot - a complete routine&lt;/h1&gt;

&lt;p&gt;Boot with LiveDVD, then&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# swapon /dev/sda7&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount /dev/sda12 /mnt/gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount /dev/sda10 /mnt/gentoo/boot&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount /dev/sda2 /mnt/gentoo/boot/efi&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cp -L /etc/resolv.conf /mnt/gentoo/etc&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount -t proc proc /mnt/gentoo/proc&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount --rbind /sys /mnt/gentoo/sys&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount --rbind /dev /mnt/gentoo/dev &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount --make-rslave /mnt/gentoo/sys &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mount --make-rslave /mnt/gentoo/dev&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# chroot /mnt/gentoo /bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# source /etc/profile &amp;amp;&amp;amp; export PS1=&quot;(chroot) $PS1&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;system-notes&quot;&gt;System notes&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Use &lt;em&gt;ffmpeg&lt;/em&gt; instead of &lt;em&gt;libav&lt;/em&gt; including the USEs.&lt;/li&gt;
  &lt;li&gt;Prefer &lt;em&gt;openssl/ssl&lt;/em&gt; USE (&lt;em&gt;dev-libs/openssl&lt;/em&gt;) to &lt;em&gt;gnutls&lt;/em&gt; USE (&lt;em&gt;net-libs/gnutls&lt;/em&gt;) for SSL/TLS secure connection. Please Google &lt;em&gt;openssl vs gnutls&lt;/em&gt;. Gnutls seems to suffer library bug.
    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;dev-libs/openssl&lt;/em&gt;: full-strength general purpose cryptography library (including SSL and TLS).&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;net-libs/gnutls&lt;/em&gt;: a TLS 1.2 and SSL 3.0 implementation for the GNU project.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Vaapi&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;ffmpeg&lt;/em&gt;, &lt;em&gt;mesa&lt;/em&gt;, &lt;em&gt;mpv&lt;/em&gt;, and &lt;em&gt;firefox&lt;/em&gt; enable &lt;em&gt;vaapi&lt;/em&gt; USE.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Globally USEs:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;USE=&quot;${CPU_FLAGS_X86} -bindist -qt4 -qt5 -libav vaapi&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Try to to &lt;em&gt;–with-bdeps=y&lt;/em&gt; occasionally on system update.&lt;/p&gt;

    &lt;p&gt;Updates fundamental dependencies like &lt;em&gt;git&lt;/em&gt; and &lt;em&gt;ffmpeg&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Try &lt;em&gt;–oneshot -1&lt;/em&gt; when re-merging dependencies.&lt;/p&gt;

    &lt;p&gt;This option should only be used for packages that are reachable from the @world package set (those that would NOT be removed by –depclean).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Use UUID to identify a partition instead of &lt;em&gt;/dev/sdaxy&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Python&lt;/p&gt;

    &lt;p&gt;Since python-exec-2.3 / eselect-python-20160207, the preferred method of altering Python configuration is to use the &lt;em&gt;edit&lt;/em&gt; mode that opens &lt;em&gt;python-exec.conf&lt;/em&gt; in an editor. The previous &lt;em&gt;set&lt;/em&gt; mode is deprecated.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# eselect python list/edit`.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;For example, remove Python 3.4 after upgrading to 3.5.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Perl&quot;&gt;Perl update&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;The official way of upgrading Perl, e.g. from Perl 5.22 to Perl 5.24, is upgrading your entire &lt;em&gt;world&lt;/em&gt; set, and upgrading Perl with it.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avtuDN --with-bdeps=y --backtrack 30 @world&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# perl-cleaner --all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;If 30 does not help, try 100 instead.&lt;/li&gt;
      &lt;li&gt;Attention: both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--with-bdeps=y&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--backtrack 30&lt;/code&gt; are required.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Upgrading_GCC&quot;&gt;upgrading Gcc&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;After upgrading from 4.9 to 5.4, I encountered &lt;a href=&quot;https://forums.gentoo.org/viewtopic-t-1049882-start-0.html&quot;&gt;librime-1.2.9 bug&lt;/a&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# gcc-config --list-profiles&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# gcc-config 2&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# env-update &amp;amp;&amp;amp; source /etc/profile&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# emerge -av1 sys-devel/libtool&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# gcc --version&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# emerge -avc =sys-devel/gcc-4.9.4&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# revdep-rebuild --library &apos;libstdc++.so.6&apos; -- --exclude gcc (opt)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The last comman triggers over 60 packages rebuild.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Keyboard_shortcuts#Kernel_(SysRq)&quot;&gt;SysRq&lt;/a&gt;
    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt - SysRq/PrintScreen - &amp;lt;argument&amp;gt;&lt;/code&gt; simutaneously; ThinkPad Fn is not required.&lt;/li&gt;
      &lt;li&gt;Or press the key one by one: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[Fn] - SysRq&lt;/code&gt;, and &lt;em&gt;argument&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;The detailed &lt;em&gt;arguments&lt;/em&gt; can be found at &lt;a href=&quot;https://www.kernel.org/doc/html/latest/admin-guide/sysrq.html&quot;&gt;kernel sysrq&lt;/a&gt;. I generally unraw(r), sync(s), umount(u), and/or reboot(b) when my system is &lt;em&gt;dead&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;x-window-system&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/X_Window_System&quot;&gt;X Window System&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;X Window System, X11, and X (shortname) are used interchangebly.&lt;/p&gt;

    &lt;p&gt;X originated at the Massachusetts Institute of Technology (MIT) in 1984. The protocol has been version 11 (hence &quot;X11&quot;) since September 1987.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Xorg/Configuration&quot;&gt;Xorg&lt;/a&gt; Server.
    &lt;ol&gt;
      &lt;li&gt;Mainly &lt;em&gt;x11-base/xorg-server&lt;/em&gt; (depending on &lt;em&gt;x11-base/xorg-drivers&lt;/em&gt; and &lt;em&gt;x11-libs/mesa&lt;/em&gt;).&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;vaapi&lt;/em&gt; USE is enabled to utilize &lt;a href=&quot;/2019/03/11/x/#hardware-acceleration&quot;&gt;hardware acceleration&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;The &lt;em&gt;i965&lt;/em&gt; and &lt;em&gt;i915&lt;/em&gt; drivers split at system application (&lt;em&gt;media-libs/mesa&lt;/em&gt;) level. The kernel always enable &lt;em&gt;i915&lt;/em&gt; instead.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Do NOT do:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo XSESSION=&quot;Xfce4&quot; &amp;gt; /etc/env.d/90xsession&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;since &lt;em&gt;root&lt;/em&gt; does not launch X. If really need, set in &lt;em&gt;~/.bash_profile&lt;/em&gt; (detailed below). It is referenced by &lt;em&gt;/etc/X11/chooser.sh&lt;/em&gt; to determine &lt;em&gt;command&lt;/em&gt; in &lt;em&gt;/etc/X11/xinit/xinitrc&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Display Manager: GDM, LightDM, SDDM etc. DM presents we a graphical login window, equivalen of &lt;em&gt;startx&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Most display managers source &lt;em&gt;/etc/xprofile&lt;/em&gt;, &lt;em&gt;~/.xprofile&lt;/em&gt; and &lt;em&gt;/etc/X11/xinit/xinitrc.d/&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;xinit&lt;/p&gt;

    &lt;p&gt;We will use &lt;em&gt;startx&lt;/em&gt; (wrapper of &lt;em&gt;xinit&lt;/em&gt; binary) to read &lt;em&gt;~/.xinitrc&lt;/em&gt; (the default is &lt;em&gt;/etc/X11/xinit/xinitrc&lt;/em&gt; or &lt;em&gt;/etc/xdg/xfce4/xinitrc&lt;/em&gt;). One of the main functions of &lt;em&gt;~/.xinitrc&lt;/em&gt; is to dictate which client (i.e. Xfce4) for the X Window System is invoked with &lt;em&gt;startx&lt;/em&gt; or &lt;em&gt;xinit&lt;/em&gt; programs on a per-user basis.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Window Manager: Awesome, OpenBox, Xfwm4 etc.&lt;/li&gt;
  &lt;li&gt;Desktop: &lt;a href=&quot;https://wiki.gentoo.org/wiki/Xfce&quot;&gt;Xfce&lt;/a&gt; and &lt;a href=&quot;https://wiki.gentoo.org/wiki/Xfce/HOWTO&quot;&gt;Xfce/Guide&lt;/a&gt;, KDE, Gnome etc.
    &lt;ol&gt;
      &lt;li&gt;Refer to &lt;a href=&quot;https://gitweb.gentoo.org/repo/gentoo.git/tree/profiles/desc/xfce_plugins.desc&quot;&gt;XFCE_PLUGINS&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;Similar to &lt;em&gt;xfce-extra/xfce4-notifyd&lt;/em&gt;, &lt;em&gt;x11-themes/gnome-icon-theme&lt;/em&gt; can be explicitly emerged along with &lt;em&gt;xfce-base/xfce4-meta&lt;/em&gt;. Details refer to Missing icons in &lt;em&gt;Xfce4 configuration&lt;/em&gt; below.&lt;/li&gt;
      &lt;li&gt;Add &lt;em&gt;-qt4 -qt5&lt;/em&gt; to &lt;em&gt;make.conf&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;It&apos;s essential to outline the diagram of X system:
    &lt;ol&gt;
      &lt;li&gt;login shell -&amp;gt; /etc/profile -&amp;gt; .bash_profile -&amp;gt; .bashrc -&amp;gt; startx/xinit&lt;/li&gt;
      &lt;li&gt;startx is a front wrapper to xinit program. startx/xinit launch X server (Xorg/X) and X client (Xfce4).&lt;/li&gt;
      &lt;li&gt;Command: startx/xinit &lt;X client=&quot;&quot;&gt; &lt;X client=&quot;&quot; arguments=&quot;&quot;&gt; -- &lt;X server=&quot;&quot;&gt; &lt;X server=&quot;&quot; arguments=&quot;&quot;&gt;&lt;/X&gt;&lt;/X&gt;&lt;/X&gt;&lt;/X&gt;&lt;/li&gt;
      &lt;li&gt;Without command line options, startx try to parse .xinitrc and .xserver respectively.&lt;/li&gt;
      &lt;li&gt;Put environment variables for GUI applications into &lt;em&gt;~/.xinitrc&lt;/em&gt; while for terminal into &lt;em&gt;~/.bashrc&lt;/em&gt; or &lt;em&gt;~/.bash_profile&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;x-configuration&quot;&gt;X Configuration&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Per-user &lt;a href=&quot;/2016/11/23/theme/&quot;&gt;Theming&lt;/a&gt; locations:
    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;*.desktop&lt;/em&gt; file should be placed in &lt;em&gt;~/.local/share/applications/&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Themes are placed in &lt;em&gt;~/.local/share/themes/&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Icons are placed in &lt;em&gt;~/.local/share/icons/&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;consolekit&lt;/em&gt; is emerged as dependency during X installation. But &lt;em&gt;Shutdown&lt;/em&gt;, &lt;em&gt;Suspend&lt;/em&gt; etc. are greyed after getting into Xfce4.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;sys-auth/consolekit pm-utils&quot; &amp;gt;&amp;gt; /etc/portage/package.use/consolekit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt consolekit&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-update add consolekit default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Xinitrc&quot;&gt;Xinit&lt;/a&gt; (Dispaly Manager)&lt;/p&gt;

    &lt;p&gt;The default OpenRC Xinit conguration is located under &lt;em&gt;/etc/X11/xinit&lt;/em&gt;. Customization:&lt;/p&gt;

    &lt;p&gt;First get a copy of the default. The reason of doing this (instead of creating one from scratch) is to preserve some desired default behaviour in the original file, such as sourcing shell scripts from &lt;em&gt;/etc/X11/xinit/xinitrc.d&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cp /etc/X11/xinit/xinitrc ~/.xinitrc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The default Xinitrc examines Xresources and Xmodmap and prepares Consolekit and Dbus. The last section either tries &lt;em&gt;twm&lt;/em&gt; and &lt;em&gt;xterm&lt;/em&gt; or lanuches XSESSION. We can change &lt;em&gt;exec $command&lt;/em&gt; to &lt;em&gt;echo $command&lt;/em&gt; and test the script within virtual terminal (console). It looks like:&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;ck-launch-session dbus-launch –sh-syntax –exit-with-session /etc/X11/Sessions/Xfce4&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;The default is enough to launch Xfce4 desktop. However we might require extra stuff like:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Refer to /etc/X11/xinit/xinitrc
# or replace &apos;startxfce4&apos; with &apos;xfce4-session&apos;:

#exec ck-launch-session dbus-launch --sh-syntax --exit-with-session xfce4-session
exec $command
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;startx&lt;/em&gt;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# startx -- vt7 -nolisten tcp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Arguments after two bashes are passed to Xorg server.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;The &lt;em&gt;xserverrc&lt;/em&gt; file is a shell script responsible for starting up the Xorg server. Both &lt;em&gt;startx&lt;/em&gt; and &lt;em&gt;xinit&lt;/em&gt; execute &lt;em&gt;~/.xserverrc&lt;/em&gt; if it exists, &lt;em&gt;startx&lt;/em&gt; will use default &lt;em&gt;/etc/X11/xinit/xserverrc&lt;/em&gt; otherwise.&lt;/li&gt;
      &lt;li&gt;Attention, &lt;em&gt;-nolisten tcp&lt;/em&gt; is to disallow TCP connection to X server.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;vt7&lt;/em&gt; must be appended, otherwise switches between X and virtual terminal would freeze the whole X seesion to death. Refer to &lt;a href=&quot;/2016/09/10/intel-graphics/&quot;&gt;Intel HD3000 Tearing/Corruption/Glitch&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;The default &lt;em&gt;/etc/X11/xinit/xserverrc&lt;/em&gt; fails to set the correct virtual terminal to start X server. It depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$XDG_VTNR&lt;/code&gt; which is not available on OpenRC &lt;a href=&quot;https://www.freedesktop.org/wiki/Software/systemd/writing-display-managers/&quot;&gt;but Systemd&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;An alternative is:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# cp /etc/X11/xinit/xserverrc ~/.xserverrc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Modify a little bit:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/bin/sh
if [ -z &quot;$XDG_VTNR&quot; ]; then
  exec /usr/bin/X -nolisten tcp &quot;$@&quot; vt7
else
  exec /usr/bin/X -nolisten tcp &quot;$@&quot; vt$XDG_VTNR
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If a Display Manager is used, those arguments would be handled correctly without user concern.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Automatic Xfce4 on login&lt;/p&gt;

    &lt;p&gt;Edit &lt;em&gt;~/.bash_profile&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/skel/.bash_profile

# This file is sourced by bash for login shells.  The following line
# runs your .bashrc and is recommended by the bash info pages.
if [[ -f ~/.bashrc ]] ; then
        . ~/.bashrc
fi

# If ~/.xinitrc does not exist, startx takes it as a fallback
XSESSION=&quot;Xfce4&quot;

if shopt -q login_shell; then
        [[ -t 0 &amp;amp;&amp;amp; $(tty) == /dev/tty1 &amp;amp;&amp;amp; &quot;$USER&quot; == &quot;username&quot; &amp;amp;&amp;amp; ! $DISPLAY ]] &amp;amp;&amp;amp; exec startx -- vt7 -nolisten tcp
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;If &lt;em&gt;~/.xserverrc&lt;/em&gt; exists, &lt;em&gt;vt7 -nolisten tcp&lt;/em&gt; part can be removed.&lt;/li&gt;
      &lt;li&gt;If you would like to remain logged in when the X session ends, remove &lt;em&gt;exec&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Clear Xfce configuration&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# rm -r ~/.cache/sessions&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rm -r ~/.config/xfce*&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rm -r ~/.config/Thunar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Hide unmounted partitions from user interface (opt)&lt;/p&gt;

    &lt;p&gt;When you get into the Xfce4 desktop, you may found many unnecessary disk icons on the desktop or thunar sidebar. It&apos;s annoying. Use &lt;em&gt;udev/udisks&lt;/em&gt; utility.&lt;/p&gt;

    &lt;p&gt;Edit &lt;em&gt;/etc/udev/rules.d/80-hide-disks.rules&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ENV{ID_FS_UUID}==&quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX&quot;, ENV{UDISKS_IGNORE}=&quot;1&quot;
or
KERNEL==&quot;sdaXY&quot;, ENV{UDISKS_IGNORE}=&quot;1&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;To load the new rules without reboot:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# udevadm control --reload&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# udevadm trigger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;XY is the disk partition number you would like to hide. As noted in the reference below, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UDISKS_PRESENTATION_HIDE&lt;/code&gt; is deprecated and replaced by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UDISKS_IGNORE&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Refer to &lt;em&gt;/lib64/udev/rules.d/80-udisks2.rules&lt;/em&gt;, read section:&lt;/p&gt;

        &lt;blockquote&gt;
          &lt;p&gt;Devices which should not be display in the user interface&lt;/p&gt;
        &lt;/blockquote&gt;
      &lt;/li&gt;
      &lt;li&gt;Refer to &lt;a href=&quot;https://superuser.com/q/695791&quot;&gt;udev 99-hide-disks.rules is no longer working&lt;/a&gt; and &lt;a href=&quot;https://wiki.archlinux.org/index.php/Udisks&quot;&gt;udisks on archwiki&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Touchpad&lt;/p&gt;

    &lt;p&gt;If Touchpad does not support &lt;em&gt;tap click&lt;/em&gt;. As long as &lt;em&gt;x11-drivers/xf86-input-synaptics&lt;/em&gt; is installed, a default configuration is located at &lt;em&gt;/usr/share/X11/xorg.conf.d/50-synaptics.conf&lt;/em&gt;. Copy it to &lt;em&gt;/etc/X11/xorg.conf.d/&lt;/em&gt; and edit:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Section &quot;InputClass&quot;
    Identifier &quot;touchpad&quot;
    Driver &quot;synaptics&quot;
    MatchIsTouchpad &quot;on&quot;
        Option &quot;TapButton1&quot; &quot;1&quot;
        Option &quot;TapButton2&quot; &quot;2&quot;
        Option &quot;TapButton3&quot; &quot;3&quot;
        Option &quot;VertEdgeScroll&quot; &quot;on&quot;
        Option &quot;VertTwoFingerScroll&quot; &quot;on&quot;
        Option &quot;HorizEdgeScroll&quot; &quot;on&quot;
        Option &quot;HorizTwoFingerScroll&quot; &quot;on&quot;
        Option &quot;CircularScrolling&quot; &quot;on&quot;
        Option &quot;CircScrollTrigger&quot; &quot;2&quot;
        Option &quot;EmulateTwoFingerMinZ&quot; &quot;40&quot;
        Option &quot;EmulateTwoFingerMinW&quot; &quot;8&quot;
        Option &quot;CoastingSpeed&quot; &quot;0&quot;
        Option &quot;FingerLow&quot; &quot;35&quot;
        Option &quot;FingerHigh&quot; &quot;40&quot;
        Option &quot;MaxTapTime&quot; &quot;125&quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;You can also set a temporary config at command line. Check command line &lt;em&gt;synclient&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;new-plug-in-sync-system---laymanoverlay&quot;&gt;New &lt;em&gt;plug-in sync system&lt;/em&gt; - Layman/Overlay&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Layman adds, removes, syncs etc. Overlays on system.&lt;/li&gt;
  &lt;li&gt;With the help of Portage new &lt;em&gt;plug-in sync system&lt;/em&gt;, Overlays can be easily synced by Portage &lt;em&gt;emaint&lt;/em&gt;. Therefore, Layman is purely used to add/remove Overlays.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;From &lt;em&gt;2.3.0&lt;/em&gt; onwards, Layman supports the new &lt;em&gt;plug-in sync system&lt;/em&gt; naturally. But current stable version is &lt;em&gt;2.0.0&lt;/em&gt;. Ether accept &lt;em&gt;2.3.0&lt;/em&gt; or manually write new &lt;em&gt;plug-in sync&lt;/em&gt; configurations for newly added Overlays.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt app-portage/layman&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;By default, the &lt;em&gt;subversion&lt;/em&gt; USE is not enabled, which support &lt;em&gt;subversion&lt;/em&gt;-based Overlays.&lt;/p&gt;

    &lt;p&gt;After emerging &lt;em&gt;&amp;lt;layman-2.3.0&lt;/em&gt;, don&apos;t do any configuration (i.e. &lt;em&gt;PORTDIR&lt;/em&gt;, &lt;em&gt;PORTDIR_OVERLAY&lt;/em&gt;) as told on Wiki since we will manually add new &lt;em&gt;plug-in sync system&lt;/em&gt; configuration.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add/remove an Overlay:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# layman -a gentoo-zh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# layman -d gentoo-zh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Manual Overlay configuration (&lt;em&gt;&amp;lt;layman-2.3.0&lt;/em&gt;)&lt;/p&gt;

    &lt;p&gt;Add &lt;em&gt;/etc/portage/repos.conf/gentoo-zh.conf&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[gentoo-zh]
location = /var/lib/layman/gentoo-zh
sync-type = git
sync-uri = git://github.com/microcai/gentoo-zh.git
auto-sync = yes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;We choose &lt;em&gt;git&lt;/em&gt; instead of traditional &lt;em&gt;rsync&lt;/em&gt;. If needed, official Portage tree &lt;em&gt;gentoo.conf&lt;/em&gt; can be changed to &lt;em&gt;git&lt;/em&gt; type as well.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Portage tree switch to &lt;em&gt;git&lt;/em&gt; sync&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# mv /usr/portage/distfiles ~/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mv /usr/portage/packages ~/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rm -rf /usr/portage/*&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emaint sync -r gentoo&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mv ~/distfiles /usr/portage&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mv ~/packages /usr/portage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;We delete the Portage tree and &lt;em&gt;emaint sync -r&lt;/em&gt; will &lt;em&gt;git clone&lt;/em&gt; locally. Refer to &lt;a href=&quot;http://blog.yjl.im/2015/05/going-gentoo-portage-git-sync.html&quot;&gt;Portage git sync&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(opt) Sync&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# eix-sync, or&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emaint sync&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;applications&quot;&gt;Applications&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Xfce4 goodies&lt;/p&gt;

    &lt;p&gt;xfce4-power-manager; xfce-extra/xfce4-pulseaudio-plugin and media-sound/pavucontrol; xfce4-screenshooter.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;Go to Applications &amp;gt; Settings &amp;gt; Keyboard, Application Shortcuts. Add the &lt;em&gt;xfce4-screenshooter -r&lt;/em&gt; command to use the PrtSc key.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Recommendations&lt;/p&gt;

    &lt;p&gt;apg, &lt;s&gt;guake&lt;/s&gt;, &lt;s&gt;st term&lt;/s&gt;, rxvt-unicode, wgetpaste, weechat, wps-office, evince, &lt;a href=&quot;/2015/08/29/texlive-gentoo/&quot;&gt;TeXLive&lt;/a&gt;, remmina/freerdp.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/IamDH4/ttf-wps-fonts&quot;&gt;wps math formula fonts&lt;/a&gt; and &lt;a href=&quot;/2015/04/13/fontconfig/&quot;&gt;fontconfig&lt;/a&gt;. Those fonts are essential to display formulas. However, WPS-linux does not have built-in formula creation function due to copyright.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Sound - ALSA/&lt;a href=&quot;https://wiki.gentoo.org/wiki/PulseAudio&quot;&gt;PulseAudio&lt;/a&gt;
    &lt;ol&gt;
      &lt;li&gt;PulseAudio depends on (both kernel and package parts) of ALSA - they coexist instead of excluding each other. It serves as a proxy to sound applications using existing kernel sound components like ALSA or OSS.&lt;/li&gt;
      &lt;li&gt;ALSA includes both kernel sound card drivers and userspace package &lt;em&gt;media-libs/alsa-lib&lt;/em&gt;, while PulseAudio builds on top of ALSA kernel part while offering userspace package &lt;em&gt;media-sound/pulseaudio&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;PulseAudio is configured to automatically detect all sound cards and manage them. It takes control of all detected ALSA devices and redirect all audio streams to itself, making the PulseAudio daemon the central configuration point.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Check if &lt;em&gt;alsa-lib&lt;/em&gt; and &lt;em&gt;alsa-utils&lt;/em&gt; are installed or not. By default, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alsa&lt;/code&gt; USE flag is enabled in profile, so these packages should be emerged already.&lt;/p&gt;

    &lt;p&gt;By default system sound is muted. Use &lt;em&gt;alsamixer&lt;/em&gt; to unmoute:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;alsamixer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;To test sound:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# speaker-test -t wav -c 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Enable global &lt;em&gt;pulseaudio&lt;/em&gt; USE:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /etc/portage/make.conf&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# euse -E pulseaudio&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# remove all users from *audio* group&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# gpasswd -d username audio&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# emerge -avtuDN --with-bdeps=y @world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Enabling &lt;em&gt;pulseaudio&lt;/em&gt; USE flag will pull in &lt;em&gt;media-sound/pulseaudio&lt;/em&gt; automatically.&lt;/li&gt;
      &lt;li&gt;If you plan running &lt;em&gt;pulseaudio&lt;/em&gt; in the &lt;a href=&quot;https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/PerfectSetup/&quot;&gt;system-wide mode&lt;/a&gt;, then the special user &lt;em&gt;pulse&lt;/em&gt; should still be in the &lt;em&gt;audio&lt;/em&gt; group in order to have access to the sound card.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;GStreamer support:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gconftool-2 &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; string &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; /system/gstreamer/0.10/default/audiosink pulsesink
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;gconftool-2 &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; string &lt;span class=&quot;nt&quot;&gt;--set&lt;/span&gt; /system/gstreamer/0.10/default/audiosrc pulsesrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;blockquote&gt;
      &lt;p&gt;From what we&apos;ve done, you know &lt;em&gt;enabling pulseaudio&lt;/em&gt; is quite easy as no kernel options required like ALSA.&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;p&gt;&lt;em&gt;xfce4-pulseaudio-plugin&lt;/em&gt; reports &quot;pavucontrol binary not found&quot;:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@tux / &lt;span class=&quot;c&quot;&gt;# emerge -avt media-sound/pavucontrol&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Firefox&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;To make use of &lt;em&gt;vaapi&lt;/em&gt;, make sure &lt;em&gt;ffmpeg&lt;/em&gt; and &lt;em&gt;hwaccel&lt;/em&gt; USEs are enabled. BTW, &lt;em&gt;ffmpeg&lt;/em&gt; should enable &lt;em&gt;vaapi&lt;/em&gt; USE too.&lt;/li&gt;
      &lt;li&gt;For Media Source Extensions, turn on &lt;em&gt;media.fragmented-mp4.exposed&lt;/em&gt;, &lt;em&gt;media.fragmented-mp4.ffmpeg.enabled&lt;/em&gt;, &lt;em&gt;media.mediasource.enabled&lt;/em&gt;, &lt;em&gt;media.mediasource.mp4.enabled&lt;/em&gt; and &lt;em&gt;media.mediasource.webm.enabled&lt;/em&gt; in &lt;em&gt;about:config&lt;/em&gt;, while disabling &lt;em&gt;media.fragmented-mp4.use-blank-decoder&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Add FoxyProxy Standard, uBlock Origin, NoScript (and/or RefControl), HTTPS Everywhere, DISCONNECT, Open With etc. add-ons. Remove unecessary default whitelist of NoScript plugin.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;privacy.trackingprotection.enabled&lt;/em&gt;, &lt;em&gt;Network.proxy.socks_remote_dns&lt;/em&gt; to True.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;network.IDN_show_punycode&lt;/em&gt; to be True.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;browser.cache.check_doc_frequency&lt;/em&gt; set to &lt;a href=&quot;https://superuser.com/a/411826&quot;&gt;0/1/2/3&lt;/a&gt;; Ctrl + Shift + I, Gear, Advanced Settings, Disable Cache (when toolbox is open).&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://vikingvpn.com/cybersecurity-wiki/browser-security/guide-hardening-mozilla-firefox-for-privacy-and-security&quot;&gt;Harden Firefox security&lt;/a&gt; and &lt;a href=&quot;http://www.howtogeek.com/113439/how-to-change-your-browsers-user-agent-without-installing-any-extensions/&quot;&gt;disable useragent&lt;/a&gt;. Like &lt;em&gt;general.useragent.vendor/override&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://panopticlick.eff.org&quot;&gt;fingerprint test&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Fcitx&quot;&gt;Fcitx&lt;/a&gt;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;app-i18n/fcitx gtk gtk3 -table&quot; &amp;gt;&amp;gt; /etc/portage/package.use/fcitx&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -av fcitx fcitx-rime fcitx-configtool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;table&lt;/em&gt; USE will draw several built-in input methods (i.e. Wubi) which fail to meet my requirement. &lt;em&gt;fcitx-rime&lt;/em&gt; will be installed instead.&lt;/li&gt;
      &lt;li&gt;I have disabled the QT globally. So no &lt;em&gt;qt4&lt;/em&gt; or &lt;em&gt;qt5&lt;/em&gt; USE.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;fcitx-configtool&lt;/em&gt; is a GTK configuration tool. To install QT configuration tool for KDE, install &lt;em&gt;kcm-fcitx&lt;/em&gt;.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Put the following lines before &lt;em&gt;exec&lt;/em&gt; of &lt;em&gt;~/.xinitrc&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=xim
export XMODIFIERS=&quot;@im=fcitx&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;They should be &lt;em&gt;ahead&lt;/em&gt; of &lt;em&gt;exec startxfce4&lt;/em&gt; or &lt;em&gt;xfce4-session&lt;/em&gt;. Commands after &lt;em&gt;exec&lt;/em&gt; won&apos;t be executed! Refer to &lt;a href=&quot;https://bbs.archlinuxcn.org/viewtopic.php?pid=13921&quot;&gt;xfce4安装fcitx不能激活！很简单的一个原因！&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;FFmpeg&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# echo &quot;media-video/ffmpeg vaapi librtmp openssl vpx&quot; &amp;gt;&amp;gt; /etc/portage/package.use/ffmpeg
# emerge -avt ffmpeg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;ffmpeg&lt;/em&gt; is emerged by some other packages, one of which might be Firefox or Mpv.&lt;/li&gt;
      &lt;li&gt;Add &lt;em&gt;-libav&lt;/em&gt; to &lt;em&gt;make.conf&lt;/em&gt; in favor of system-wide &lt;em&gt;ffmpeg&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;v4l&lt;/em&gt; and &lt;em&gt;libv4l&lt;/em&gt;USE for the webcamera.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;vaapi&lt;/em&gt; USE for &lt;a href=&quot;/2019/03/11/x/#hardware-acceleration&quot;&gt;hardware decoding&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;librtmp&lt;/em&gt; USE to replace the native RTMP implementation (bad performance).&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;network&lt;/em&gt; (default) and &lt;em&gt;openssl&lt;/em&gt; to support HTTP/HTTPS streaming.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mpv&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# echo &quot;media-video/mpv vaapi&quot; &amp;gt;&amp;gt; /etc/portage/package.use/mpv&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# echo &quot;=media-video/mpv-9999 **&quot; &amp;gt;&amp;gt; /etc/portage/package.keywords/mpv&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -avt mpv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;You are recommended to accpet &lt;em&gt;mpv&lt;/em&gt; live build.&lt;/li&gt;
      &lt;li&gt;Rely on &lt;em&gt;ffmpeg&lt;/em&gt; and &lt;em&gt;youtube-dl&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Enable &lt;em&gt;vaapi&lt;/em&gt; USE for &lt;em&gt;mpv&lt;/em&gt; and *ffmpeg to utilize hardware acceleration.&lt;/li&gt;
      &lt;li&gt;Re-merge &lt;em&gt;mpv&lt;/em&gt; if &lt;a href=&quot;https://wiki.gentoo.org/wiki/Mpv#Broken_playback.2Fcrashes_after_updating_FFmpeg.2FLibav.2Flibass.2Fetc.&quot;&gt;&lt;em&gt;ffmpeg&lt;/em&gt; is upgraded&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;The default &lt;em&gt;lua&lt;/em&gt; USE flag of &lt;em&gt;mpv&lt;/em&gt; brings along a &lt;em&gt;youtube-dl&lt;/em&gt; hook script. &lt;em&gt;mpv url&lt;/em&gt; revokes &lt;em&gt;youtube-dl&lt;/em&gt; to stream video playback.&lt;/p&gt;

        &lt;p&gt;And make sure &lt;em&gt;ffmpeg&lt;/em&gt; is installed with &lt;em&gt;network&lt;/em&gt; USE flag. To stream HTTPS url, enable either &lt;em&gt;openssl&lt;/em&gt; or &lt;em&gt;gnutls&lt;/em&gt; USE of &lt;em&gt;ffmpeg&lt;/em&gt;. Ether &lt;em&gt;openssl&lt;/em&gt; is fine and you don&apos;t need both.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;em&gt;youtube-dl&lt;/em&gt; is suggested to install under Python3 virtual environment by &lt;em&gt;pyvenv-3.4&lt;/em&gt; thus receving immediate updates. If &lt;em&gt;youtube-dl&lt;/em&gt; does not stream Chinese url, try &lt;em&gt;mpv $(youtube-dl –get-url http://v.youku.com/v_show/id_XMTU2Mjc4MTc4NA==.html)&lt;/em&gt;.&lt;/p&gt;

        &lt;p&gt;After installing &lt;em&gt;youtube-dl&lt;/em&gt; in Python3 virtual environment:&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sf&lt;/span&gt; /absolute/path/to/py3venv/youtube-dl ~/.config/mpv/youtue-dl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;If &lt;em&gt;youtube-dl&lt;/em&gt; sucks, could try &lt;em&gt;you-get&lt;/em&gt; (for Chinese urls) and &lt;em&gt;livestreamer&lt;/em&gt; (for live broadcast). If the url is blocked, we should first enable &lt;em&gt;proxychains&lt;/em&gt; or &lt;em&gt;torify&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;When streaming, &lt;em&gt;mpv&lt;/em&gt; might throtle/stuck a lot waiting for cache. This is due to ISP throtling; video provider streaming limit; network bandwidth etc.
        &lt;ol&gt;
          &lt;li&gt;Set bigger &lt;em&gt;–cache&lt;/em&gt; value; press SPACE to pause for fechting more cache.&lt;/li&gt;
          &lt;li&gt;Run &lt;em&gt;youtube-dl url&lt;/em&gt; and &lt;em&gt;mpv partial-downloaded-file&lt;/em&gt; separately (say in two terminals). If does not play the partial file (HASH video and audio are usually downloaded separately), try &lt;em&gt;-f best&lt;/em&gt; argument which tell to download audio and video into a single file. If downloading audio and video separately, there would be no audio or video when playing.&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;We can use Firefox addons &lt;em&gt;Open With&lt;/em&gt; to revoke &lt;em&gt;mpv&lt;/em&gt;.&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/usr/bin/proxychains /usr/bin/mpv  --
or
~/workspace/virtualenv3/bin/you-get -p /usr/bin/mpv --
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;The last two hypens means arguments afterwards are input files/urls. Since using the &lt;em&gt;Open With&lt;/em&gt; addon, save more CPU and memory than Firfox.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Details on &lt;a href=&quot;https://github.com/rg3/youtube-dl&quot;&gt;&lt;em&gt;youtube-dl&lt;/em&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/soimort/you-get&quot;&gt;&lt;em&gt;you-get&lt;/em&gt;&lt;/a&gt;, refer to their Github pages.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Some videos with &lt;em&gt;aac&lt;/em&gt; audio track won&apos;t show video (only audio). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-v --no-config&lt;/code&gt; gives:&lt;/p&gt;

        &lt;blockquote&gt;
          &lt;p&gt;[lavf] Edit lists are not correctly supported (FFmpeg issue).&lt;/p&gt;
        &lt;/blockquote&gt;

        &lt;p&gt;Before &lt;em&gt;ffmpeg&lt;/em&gt; fixes the &lt;em&gt;edit list&lt;/em&gt; parsing, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--demuxer-lavf-o=ignore_editlist=1&lt;/code&gt; option.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Emacs
    &lt;ol&gt;
      &lt;li&gt;Use &lt;em&gt;athena Xaw3d -gtk -gtk3 -motif&lt;/em&gt;  USEs to replace GTK toolkit if multiple monitors are used. Refer to &lt;em&gt;daemon mode&lt;/em&gt; bug &lt;a href=&quot;https://www.reddit.com/r/emacs/comments/2ans0z/have_you_encountered_that_gtk_bug_in_daemon_mode/?ref=share&amp;amp;ref_source=link&quot;&gt;reddit&lt;/a&gt; and &lt;a href=&quot;https://wiki.gentoo.org/wiki/GNU_Emacs&quot;&gt;wiki&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;xft&lt;/em&gt; for Fontconfig. &lt;em&gt;libxml2&lt;/em&gt; support &lt;em&gt;shr&lt;/em&gt; enables &lt;em&gt;eww&lt;/em&gt; HTML viewer. &lt;em&gt;gnutls/ssl&lt;/em&gt; supports Gnus IMAP connection.&lt;/li&gt;
      &lt;li&gt;Chinese input with Fcitx. Change the Fcitx input method trigger to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WIN+I&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CTRL+SPACE&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;If X frame does not input Chinese, emerge two fonts: &lt;em&gt;font-adobe-100dpi&lt;/em&gt; and &lt;em&gt;font-adobe-75dpi&lt;/em&gt;. You can read post-emerge message:&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if use X; then
    elog &quot;You need to install some fonts for Emacs.&quot;
    elog &quot;Installing media-fonts/font-adobe-{75,100}dpi on the X server&apos;s&quot;
    elog &quot;machine would satisfy basic Emacs requirements under X11.&quot;
    elog &quot;See also http://www.gentoo.org/proj/en/lisp/emacs/xft.xml&quot;
    elog &quot;for how to enable anti-aliased fonts.&quot;
    elog
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;em&gt;emacs-daemon&lt;/em&gt;&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt emacs-daemon&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cd /etc/init.d/&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ln -sv emacs emacs.usernmae&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-update add emacs.username default, (do NOT add */etc/init.d/emacs* to default runlevel directly)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# rc-service emacs.username start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;XIM&lt;/p&gt;

        &lt;p&gt;Since &lt;em&gt;emacs-daemon&lt;/em&gt; is launched before (OpenRC init) setting variable (XMODIFIERS=&quot;@im=fcitx&quot; by &lt;em&gt;startx&lt;/em&gt; in &lt;em&gt;~/.xinitrc&lt;/em&gt;), &lt;em&gt;emacsclient -c&lt;/em&gt; cannot find external Fcitx&apos;s XIM server. Possible solutions:&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#/etc/init.d/emacs.username&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;SHELL EMACS EMACS_TIMEOUT EMACS_DEBUG
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;XMODIFIERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;@im&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;fcitx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;We set the variable in init &lt;em&gt;start()&lt;/em&gt; function. Alternatively, set XMODIFIERS through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--env&lt;/code&gt; argument of &lt;em&gt;start-stop-daemon&lt;/em&gt;.&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;start-stop-daemon &lt;span class=&quot;nt&quot;&gt;--start&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USER&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--pidfile&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PIDFILE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--chdir&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;home&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--env&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;XMODIFIERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;@im=fcitx&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--exec&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;EMACS_START&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
 &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;EMACS_OPTS&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;However, direct modification init script is discouraged (suppose you are on a multiple user accounts system). &lt;em&gt;emacs-daemon&lt;/em&gt; has a wrraper script (&lt;em&gt;/usr/libexec/emacs/emacs-wrapper.sh&lt;/em&gt;) to start the daemon &lt;em&gt;with a login shell&lt;/em&gt;. We can set XMODIFIERS in bash startup script (&lt;em&gt;~/.bashrc&lt;/em&gt; or &lt;em&gt;~/.bash_profile&lt;/em&gt;).&lt;/p&gt;

        &lt;p&gt;A more elegant way is to create a new copy of &lt;em&gt;/etc/conf.d/emacs&lt;/em&gt; and do update there:&lt;/p&gt;

        &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# pushd /etc/conf.d&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# cp emacs emacs.username&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# nano -w emacs.username&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;XMODIFIERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;@im=fcitx&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;Don&apos;t worry! &lt;em&gt;openrc-run&lt;/em&gt; looks for both &lt;em&gt;/etc/conf.d/emacs&lt;/em&gt; and &lt;em&gt;/etc/conf.d/emacs.username&lt;/em&gt;.&lt;/p&gt;

        &lt;p&gt;Emacs uses XIM to support external input method instead of GTK/QT toolkit. Details on XMODIFIERS/XIM, refer to Fcitx&apos;s official page. Read more at &lt;a href=&quot;https://stackoverflow.com/a/34852916&quot;&gt;fcitx not work on &lt;em&gt;emacsclient –create-frame&lt;/em&gt;&lt;/a&gt; and &lt;a href=&quot;https://bugs.gentoo.org/show_bug.cgi?id=246460&quot;&gt;app-emacs/emacs-daemon should allow for setting up a proper environment&lt;/a&gt;.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Nano&lt;/p&gt;

    &lt;p&gt;After installing Emacs, &lt;em&gt;nano&lt;/em&gt; will be removed on next &lt;em&gt;emerge -avc&lt;/em&gt; (check package &lt;em&gt;virtual/editor&lt;/em&gt;). To keep &lt;em&gt;nano&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c&quot;&gt;# emerge -avt --noreplace nano&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Turn on a few Nano options in &lt;em&gt;/etc/nanorc&lt;/em&gt;: &lt;em&gt;set autoindent&lt;/em&gt;, &lt;em&gt;set backup&lt;/em&gt;, &lt;em&gt;set tabsize 4&lt;/em&gt; etc. If need to totally disable an option, use *unset &lt;option&gt;*.&lt;/option&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Archive&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -av file-roller&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# emerge -av thunar-archive-plugin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;file-roller&lt;/em&gt; is a front-end GTK interface - Archive Manager, which needs background Archiver support - &lt;em&gt;zip/unzip&lt;/em&gt;, &lt;em&gt;bzip2&lt;/em&gt;, &lt;em&gt;tar&lt;/em&gt;, &lt;em&gt;7zip&lt;/em&gt;, &lt;em&gt;unrar&lt;/em&gt; etc.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;thunar-archive-plugin&lt;/em&gt; is a Thunar plugin (right-click menu). If &lt;em&gt;thunar-archive-plugin&lt;/em&gt; cannot find a suitable archive manager, check &lt;a href=&quot;https://forums.gentoo.org/viewtopic-t-1006838.html?sid=bce8eeef9eab8d916c59b01cef493bb4&quot;&gt;thunar archive plugin cannot integrate with file-roller&lt;/a&gt; and &lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=746504&quot;&gt;doesn&apos;t work anymore with recent file-roller&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;By default, &lt;em&gt;unzip&lt;/em&gt; cannot extract arhives containing no-ASCII file names (i.e. archives created on Chinese Windows). Enable &lt;em&gt;natspec&lt;/em&gt; USE that brings in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-O&lt;/code&gt; command line option. Check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-O&lt;/code&gt; by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-h&lt;/code&gt; as it&apos;s not present in man page. Attention, &lt;em&gt;natpsec&lt;/em&gt; requires &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LC_CTYPE&lt;/code&gt; be &lt;em&gt;zh_CN&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;(opt) &lt;em&gt;p7zip&lt;/em&gt; has a higher data compression ratio.&lt;/p&gt;

        &lt;p&gt;&lt;em&gt;p7zip&lt;/em&gt; brings 3 archive binaries, namely &lt;em&gt;7z&lt;/em&gt;, &lt;em&gt;7za&lt;/em&gt; and &lt;em&gt;7zr&lt;/em&gt;. Only &lt;em&gt;7zr&lt;/em&gt; can extract non-ascii &lt;em&gt;zip&lt;/em&gt; files. However &lt;em&gt;file-roller&lt;/em&gt; will take &lt;em&gt;7z&lt;/em&gt; and &lt;em&gt;7za&lt;/em&gt; primarily. Rename &lt;em&gt;/usr/bin/7z&lt;/em&gt; and &lt;em&gt;/usr/bin/7za&lt;/em&gt; to something else.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/darknessomi/musicbox&quot;&gt;NetEase-MusicBox&lt;/a&gt;&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt media-sound/mpg123&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/opt/pyvenv3/bin/activate
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;NetEase-MusicBox
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;pip&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;lxml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If encountered error during installing NetEase-MusicBox,&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;running build_ext
running build_configure
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... configure: error: in `/tmp/pip-build-y5q1g0ib/pycrypto&apos;:
configure: error: cannot run C compiled programs.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The reason is that &lt;em&gt;/tmp&lt;/em&gt; is mounted as &lt;em&gt;noexec&lt;/em&gt;. To temporarily solve it,&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ TMPDIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~/tmp pip&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;NetEase-MusicBox
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Read more on &lt;a href=&quot;https://github.com/pyenv/pyenv/issues/13&quot;&gt;Won&apos;t install python 2.7.4 if /tmp is mounted noexec&lt;/a&gt; and &lt;a href=&quot;https://bugs.launchpad.net/pycrypto/+bug/1294670/comments/7&quot;&gt;pip install pycrypto fails on centos 6.4&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;sphere&quot;&gt;Sphere&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Blacklist/install modules&lt;/p&gt;

    &lt;p&gt;Prevent rarely used modules from loading on boot. Always refer to command line tool &lt;em&gt;lsmod&lt;/em&gt;, &lt;em&gt;modinfo&lt;/em&gt; if unsure. Create &lt;em&gt;/etc/modprobe.d/blacklist.conf&lt;/em&gt; and put unwanted modules there.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/modprobe.d/blacklist.conf
blacklist btusb
blacklist btbcm
blacklist btintel
blacklist bluetooth
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;We can replace &lt;em&gt;blacklist&lt;/em&gt; with &lt;em&gt;install … true/false&lt;/em&gt; which makes a difference. A blacklisted module will be loaded if another non-blacklisted module depends on it, or if it is loaded manually. For example, &lt;em&gt;bluetooth&lt;/em&gt; is blacklisted. If we manullay &lt;em&gt;modprobe btusb&lt;/em&gt;. &lt;em&gt;bluetooth&lt;/em&gt; module will load as a dependency. Hence, it&apos;s necessary to remove related &lt;em&gt;init service&lt;/em&gt; (if exist) from runlevels. Otherwise &lt;em&gt;blacklisted&lt;/em&gt; modules were loaded.&lt;/p&gt;

    &lt;p&gt;To ensure the modules are never inserted, even if they are needed by other modules or manually &lt;em&gt;modprobe&lt;/em&gt;, use &lt;em&gt;install&lt;/em&gt;. To install a module as &lt;em&gt;true&lt;/em&gt; or &lt;em&gt;false&lt;/em&gt; does not make much difference. &lt;em&gt;false&lt;/em&gt; just files an extra error message while &lt;em&gt;true&lt;/em&gt; silence it. Refer to &lt;a href=&quot;https://github.com/OpenSCAP/scap-security-guide/issues/539&quot;&gt;Modprobe is better disabled by using &lt;em&gt;/bin/true&lt;/em&gt; (not &lt;em&gt;/bin/false&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;Refer to &lt;a href=&quot;https://wiki.archlinux.org/index.php/Kernel_modules#Blacklisting&quot;&gt;arch wiki blacklist&lt;/a&gt;; &lt;a href=&quot;https://www.archlinux.org/news/changes-to-module-blacklisting/&quot;&gt;changes to module blacklisting&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Intel Microcde (opt)&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# emerge -av microcode-ctl
# rc-update add microcode_ctl boot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Refer to &lt;a href=&quot;https://wiki.gentoo.org/wiki/Intel_microcode&quot;&gt;intel microcode&lt;/a&gt;. Updates to CPU microcode have to be re-applied each time the computer is booted, because the memory updated is volatile (despite the term &lt;em&gt;firmware&lt;/em&gt; also being used for microcode).&lt;/p&gt;

    &lt;p&gt;According to the reference, you should run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dmesg | grep -i microcode&lt;/code&gt; to check whether CPU microcode is updated or not. If not, I think there is not need to add &lt;em&gt;microcode-ctl&lt;/em&gt; to boot level until &lt;em&gt;microcode-ctl&lt;/em&gt; package is updated.&lt;/p&gt;

    &lt;p&gt;It&apos;s recommended to update CPU microcode through BIOS update. We can do this under Windows.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;(opt) swapfile&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# dd if=/dev/zero of=/mnt/1GB-swapfile bs=1M count=1024&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# chmod 600 /mnt/1GB-swapfile&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# mkswap /mnt/1GB-swapfile&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# swapon /mnt/1GB-swapfile&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# swapon -s&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ect /etc/fstab&lt;/span&gt;
/mnt/1GB-swapfile none swap defaults 0 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ol&gt;
      &lt;li&gt;Since OpenRC-0.22, please enable &lt;em&gt;rc_need=&quot;localmount&quot;&lt;/em&gt; in &lt;em&gt;/etc/conf.d/swap&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Use &lt;em&gt;dd&lt;/em&gt; to create a file occupying continuing disk space instead of a &lt;em&gt;sparse file&lt;/em&gt;. Refer to &lt;a href=&quot;https://serverfault.com/a/25708&quot;&gt;swap partition vs file for performance?&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;Refer to &lt;a href=&quot;https://wiki.archlinux.org/index.php/Swap#Swap_file_creation&quot;&gt;swap file creation&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;It is recommended to turn down &lt;em&gt;vm.swappiness&lt;/em&gt; by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysctl&lt;/code&gt;. By default, it is 60, and we can change it to 10 or so.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# /etc/sysctl.d 25-swappiness.conf

vm.swappiness=10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Big Data Notes</title>
   <link href="/2015/03/23/big-data-notes/"/>
   <updated>2015-03-23T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/03/23/big-data-notes</id>
   <content type="html">&lt;p&gt;接触big data时间不长，但是随着现在big data的兴起, 越来越多的人投入这个领域. 加上以前是做分布式系统开发的, 所以很自然地就进入了领域，一路弄下来，庆幸的是统计没白学, 这个领域我的感觉，就是cs的应用统计学，这块占了80％,剩下20％是分布式算法.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;information retrieval 没啥高深的算法，基本数据结构就是inverted list, skip list。然后加上几个matching model，用的最多的估计还是vector space或者OKAPI 25。
machine learning 实践中真正好使的都是最基本的算法吧。比较鬼扯的那些个灌水算法，加上一堆乱七
八糟regularizer或者推convergence bound的，估计也没人care，因为实际上一碰上真
实数据全不work。要么就是仅仅在小规模数据上work，碰上大数据就要算一光年或者要
1TB内存…呵呵。&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;本来我是带着娱乐的态度来回帖的，但是既然碰到了大牛，请educate我。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;请告诉我任意一个数据结构，比inverted list 更重要，并且广泛地应用到了实际的text retrieval system中。&lt;/li&gt;
  &lt;li&gt;请告诉我任意一个document retrieval model，比vector space model 或者 Okapi BM25, Statistically significantly better for general purpose document retrieval. Either implemented in Lucene or Lemur.&lt;/li&gt;
  &lt;li&gt;请告诉我任意一个clustering algorithm，other than Kmeans，will be your safe first choice of clustering when you see some arbitrary data.&lt;/li&gt;
  &lt;li&gt;对于Classification，Old Stuff Like KNN works well in many cases. Kernel algorithms are good publishing baselines, 但它们NxN 的需求极大得限制了它在大规模数据上得使用。Other algorithms like MinHash, LSH, KD-trees etc are all old.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我的论点是，工业界真正使用的算法，没有那么多fancy的东西，因为确实大多数recent publish的work都不怎么work。都是tune parameters和选择性得测试data set搞出来灌水的。一旦你拿出那些算法在大规模真实数据上一跑，大部分都不怎么work。或者tune了N久比传统算法好不了多少，还不稳定。举例来说一个work的，page rank algorithm，这还是实现在真实系统里的。你要是实现过你就知道，比起kleinberg的HITS algorithm没有什么优势，但是Google实现的好，关键是加了很多有用的不被学术界所齿的heuristics，所以效果不错。&lt;/p&gt;

&lt;p&gt;如果你确实认为近年的research极大得促进了科技得进步，改善了人类的生活，请告诉我近三年有什么publish在NIPS/ICML/WWW/KDD/COLT上的work被大规模的应用到了实际系统中，I am glad to know。我去学习。btw，deep learning去年NIPS很火，技术被google买了，那东西是彻底的刁丝翻身，NN这种没有理论得东西被statistical ML领域的人鄙视多少年了。Again，The true fact is我很菜。 我的的知识很落伍。很久没跟进最新的paper了。你要是能educate我，是个好事儿，我正好去学习。偷偷implement
一下这些牛逼算法赚个大的。&lt;/p&gt;

&lt;p&gt;After Ph.D., you may make significant contribution to the area, you may not.
Most likely not. But you will gain the ability to tell whether something is
really working or it is just &quot;claimed working&quot;. Working algorithms are usually very very simple. 忽悠algorithms are usually intentionally made complex and not working. 我觉得如果连这个都没练出来，那几百篇paper是白读了。&lt;/p&gt;

&lt;p&gt;What&apos;s the shortest lie in computer science? &quot;It works&quot;.&lt;/p&gt;

&lt;p&gt;What&apos;s the shortest truth in computer science? &quot;It sucks&quot;.&lt;/p&gt;

&lt;p&gt;没有任何冒犯做research的人的意思，我也干这个，我就是想说，虽然不时会有一些比较牛逼的算法出现，（比如像SVM，就是work）。但残酷的现实就是，绝大部分的research work都没有什么significant contribution，除了发paper没啥用。这个估计读了phd的都有感受。所以灌完水拿了个phd. ，要去工业界，不用认为自己就牛逼得不得了，好像比没读phd的高几等。&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;coding:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;JOIN: nested join, hash join, sort-merge join&lt;/li&gt;
  &lt;li&gt;Number: Fibonacci, prime，随机取文件某一行&lt;/li&gt;
  &lt;li&gt;String: strstr, wordcount&lt;/li&gt;
  &lt;li&gt;Tree: height, lca, balance tree&lt;/li&gt;
  &lt;li&gt;Heap: 查找最大的k个数&lt;/li&gt;
  &lt;li&gt;DP: 最大连续子串和&lt;/li&gt;
  &lt;li&gt;array: find a key in rotated array, 去除重复字符&lt;/li&gt;
  &lt;li&gt;linkedlist: 是否有环，插入结点，删除重复结点&lt;/li&gt;
  &lt;li&gt;递归回溯：变化很多，这方面需要大量练习&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;知识性：&lt;br /&gt;
多线程，mutex/semaphore&lt;br /&gt;
java GC&lt;br /&gt;
C++ virtual, smart pointer&lt;br /&gt;
regex使用&lt;br /&gt;
数据库：知道btree, 索引&lt;br /&gt;
search engine: 倒排表,拉链，稀疏索引，空间向量模型，tf*idf,&lt;br /&gt;
large scale data: hash, consistent hash, bloom filter, bitmap, 外排序，partition&lt;br /&gt;
分布式：CAP理论，gossip，Paxos, GFS设计思想&lt;br /&gt;
network: socket, tcp3次握手, asyschnoized io, epoll, select, 惊群&lt;/p&gt;

&lt;p&gt;设计型：&lt;br /&gt;
queue/stack实现&lt;br /&gt;
LRU&lt;br /&gt;
trie　tree&lt;br /&gt;
设计游戏&lt;br /&gt;
四则运算求值&lt;/p&gt;

&lt;p&gt;我感觉把我上面说的练熟，还是很大可能性遇到的，虽然不是很全面，但我觉得不应该把太多时间花在难题上，充实知识体系，符合职位要求更重要。&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;请问有没有python实现的数据结构和算法课？&lt;/p&gt;

&lt;p&gt;入门算法推荐berkeley的 shewchuck 的 数据结构 还有一个大作业 是一个棋牌游戏的人工智能 那个课是semester的 用java的&lt;/p&gt;

&lt;p&gt;顺便说一下 我个人感觉python实际使用起来兼容性很差 即使都是2.x 比如我使用NLTK的经历就很痛苦 每一个package弄下来都要debug 不能直接使用 逻辑bug没有 都是不兼容的bug 有些网上也找不到答案 只能看进去该函数 比如生成wordnet的网络图 我就是调用了另一个函数bird书里边的例子我都run不了而且python非常慢 我用的还是pyDEV 经常不知怎么的就死机了&lt;/p&gt;

&lt;p&gt;java大部分好技术都是java的 比如hadoop lucene weka 等等&lt;/p&gt;

&lt;p&gt;我觉得python发展很混乱 而且现在都又去学swift和node了&lt;/p&gt;

&lt;p&gt;python面试如果你不是行家 很快就可以看出来 语言本身的小技巧挺多的 所以用不好
python而用它面试属于丢人现眼了&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;老赵，你现在转战这里了？ 我觉得python vs java 的话，能够上 java 还是上 java,
python 在 hadoop world 是个怪胎. 所谓大家写的python  大部分都在后台被变成了
jython or cython. 由于隔着这1层纱，很多 performance 的问题根本没法debug.&lt;br /&gt;
python 是入门用的, 几十行的function call 用python写还行。几百行，上千行的lib
还是得用jvm 写才行。&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;big data有两套生态啊，python的scipy和java的hadoop这些我用python就不用hadoop了，直接上scipy和numpy建模容易，虽然运行很慢，但是写起来来快，不适合生产，但是适合建模用hadoop我就不用python，直接上java我们是用python来快速modelling，然后对sample做test没问题之后，再由我等java编程师转译成java代码，测试无问题后下放生产基本上对python的使用是用完就扔掉，下次要用再写，基本上都不重用java则是大量重用代码，以造可复用的轮子为主要目的. scala用来写一些类库挺好，基本上除了java以外，其他所有语言都不宜写太多，都不适合搞软件工程其实我java代码也写得不多，一般超过200行就分类了&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;千万不要被任何FP欺骗上当，function programming从来不是，现在不是，将来也不是编程的主流，相信我
这一句就行了。老老实实用传统语言，有你吃香的喝辣的，FP就是没事找事。作为开发
者，记得一句话: We are coming here to solve problem, not to create problem。&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;我发表一下看法：
过去二十年CS深受OO和互联网的影响。所有的数据和业务逻辑都被封装在大大小小的模
块里面，这样保证了能够传输，移植和复用等问题。&lt;/p&gt;

&lt;p&gt;但是被小心翼翼封装在json或者packet里面的数据已经没法流动起来了。rdbms虽然能
够处理transaction但是对于高维稀疏而且schema多变的数据也无能为力，以致于现在
最靠谱的数据共享方式还是文件或者文件的变种。&lt;/p&gt;

&lt;p&gt;所谓的大数据工具，是一种海量拆包的工具，只不过是在反过来做过去20年各种无谓的
encapsulation。可以认为互联网每天成千上百个pb的数据里面，真正有价值的部分只
是几十个tb，而其中能够分析也不过这当中的一个百分比。无论是tableau也好还是
gnip也好还是sumologic也好，做的都是这些器，这些东西十几年前都做过了，只不过
现在从pc软件变成了web service。&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;靠谱&lt;/p&gt;

&lt;p&gt;不过oo跟互联网还不是一个时代，互联网更靠后一些
oop很早就显现出了替代其他各种paradigms的架势
随之而来的是软件工程这个学科的兴起
然后逐步替换并淘汰掉c为代表的硬件/命令式编程
开始剥离出抽象的逻辑代码而非命令代码
最早做出垮平台的是fortran，字节码那些都是fortran先搞出来的
然后oop优化最早是smalltalk，以及后来的strongtalk搞出来的理论
再然后lars bak等人根据strongtalk的经验
address了sun的一个项目组用c++用疯了的问题
这就是oak以及后来的java还有官方jvm hotspot的第一版
然后就是java瞄准了网络时代，sun提出了the network is the computer
java上各种socket等的编程也远比c什么容易很多，封装得更彻底
最早c/c++什么用corba，简直不是人用的
然后java在corba基础之上搞出了rmi
再后来是ejb，ejb就是分布式系统的一个典型应用
然后ejb太过于复杂，加上m$被一脚踢出了java阵营
所以迫不及待需要一个更高level的通信协议，这就是后来xml
然后基于xml演化出了uddi, wsdl&amp;amp;soap这个web service的第一代
但是web service还是太过于复杂，于是有个phd提出了restful构架
简化了web service，然后就有了网络上各种产品比如json的今天
同时server side以ejb为代表的j2ee大规模应用，但是ejb本身也太过于复杂
rod johnson和gavin king为代表的aussie建议简化，同时orm也被提出
建议对传统db做封装，因为sql太不统一了，而且关系型数据跟oo概念有很大出入
这就有了spring和hibernate，然后spring和hibernate横行，就有了分布式今天的基础
架构
再然后，google等web公司逐步兴起，又提出了很多新概念，比如nosql和map reduce这些
后来，yahoo根据google的各种概念，作出了java版的google系统的翻版
然后贡献给了apache并开源了，其他公司就都跑去抄yahoo的这个东西，不要钱比什么
都重要
这就是hadoop，hadoop在一定程度上拓宽了传统db的范畴
这几个基本上构成了今天分布式的基础架构
再然后，这一套完成之后，人们开始想办法针对这一套架构做优化
简单说就是如何引入脚本来简化某些领域的开发，就像以前sql对db一样
这就有了ruby以及jruby，js以及rhino和nashorn，python和jython
同时jvm自身也在摸索一些更为合理的编程方式，这就是scala，groovy还有clojure
再然后，也就是一年前，更多的专业脚本语言被提出，要搬到jvm上去
这就是renjin，也就是r在jvm上的impl，以及hadoop自身发展出的类似sql的ql
比如cassandra用的cql，同时java本身也在拓展jvm的性能
java引入了script engine，随着java版本的逐步完善，以后让jvm直接执行脚本
比如python, ruby, js,groovy这些，会变得更为方便和便捷
但是jvm毕竟还是java的一部分，不懂jvm还是不行
另外很多人还在用并行计算的思维来思考分布式计算，都是hpc那些，这个也不对
不懂分布式就很难理解分布式所带来的各种问题，hadoop等都在尝试着让分布式变得更
简单
cloud也在努力使分布式变得更为简单，但是要做到无脑就用的程度
还是太遥远了，因为各种东西都很不完善，至少现阶段，还是要会java才行
否则都是toy，各种兼容性的问题，不胜其烦，生产系统可没办法这样搞
多来几个生产bugs，编程师就要准备打包滚蛋了&lt;/p&gt;

&lt;p&gt;不过这些都是empirical东西
真正的big data和分布式理论要超越这些具体的impl
理论上用什么都可以做出来，用汇编都行，但是实践是另外一回事
实际干活还是以堆轮子为首选，否则没办法维护&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;jvm也是c写的，最终什么都是c，但是c和汇编都太底层了
跟人的思维接不上，人毕竟是人，不可能完全用机器的思维方式去思考和书写语言
整个计算机系统就是层层封装的结果&lt;/p&gt;

&lt;p&gt;并行计算跟分布式计算是两回事
并行计算很多时候对于单机更有意义，共享内存这些
分布式计算一定涉及网络连接，分布式计算不在乎甚至有意识地破坏某些nodes
以测试整个系统的健壮程度，比如chaos monkey，就是要让某些nodes fail掉
看看系统work不work，并行计算用得比较多的是hpc，而不是分布式系统
分布式系统因为nodes上各种乱七八糟的系统什么良莠不齐
所以找到一个统一的平台非常重要，否则每个node都要求定制软件，工作量太大
jvm是目前能找到的最好平台
其他语言要么效率比不过jvm，要么就是兼容性比不过java&lt;/p&gt;

&lt;p&gt;hpc上的mpi这些到还真是用c比较多，物理系什么都很喜欢写pbsscript
然后提交hpc排队，执行后看结果，并行计算和分布式计算有一些共性和重叠
但是毕竟不是一个东西，不同的topics&lt;/p&gt;

&lt;p&gt;从效率上说，效率提升不只比单线程的效率
是多线程，多进程的效率提升，能并行处理的部分越多，可以提升的空间就越大
要并行处理，就需要decoupling，割裂多个模块，使之可以并行
这个要看需求，不同需求决定了dependency的多寡，一般科学计算依赖较强
web的相互依赖较弱，所以一般这种都最先用在web上&lt;/p&gt;

&lt;p&gt;还有就是效率本身，java和c的差异主要体现在内存的管理上
那效率也是由综合因素决定的，也不仅仅取决于内存操作的执行效率
还同样取决于网络，which是分布式计算一定要涉及的部分
网络的io比起内存，那是要慢太多了
一般来说操作效率cpu»内存»硬盘»网络
这里面还有什么l1 cache，l2 cache这些就都不细说了，n年不搞这些了
但是网络的latency远远高过硬盘，内存耗时这些应该是个共识
工作时候，网络的io是要尽量减少的，所以就算你辛辛苦苦用c实现了
提升了内存效率，但是还是改变不了网络的延迟，该慢还是慢，那你用c做有意义么？
木桶原理，决定高度的是最短的一块，分布式最短也就是最慢的一般都是网络操作
但是分布式又离不开网络操作，否则就不是分布式了&lt;/p&gt;

&lt;p&gt;而且割裂的平台会使得很多优化手段无法使用
一个统一的平台远比几个不同平台各搞各的要容易优化
python的包很多都是fortran, c++还有python自身写的
乱七八糟，不仅垮平台很难实现，还同时导致综合执行效率降低
c++的有些优化手段，fortran就用不了，反之亦然，因为毕竟不是一个语言
很多特性不一样，相比之下，java所有的包都是jvm上的
所有代码有一个工整的执行格式，那么优化手段就多了&lt;/p&gt;

&lt;p&gt;jvm本身在lars bak手下制作的时候，lars bak注册了23项专利
大部分都是优化专利，google后来雇用了lars bak，搞了v8引擎
结果就被oracle告了，就因为lars bak的专利
lars bak从strongtalk时代开始搞oop的优化，老鸟中的老鸟，巨牛无比
其他没有办法过他手优化的，比如ruby和python，效率就偏低，就慢
所以现在都争着往jvm上搬，什么jruby, jython, js这些，都有jvm的版本
到了jvm，就能用上lars bak的东西了，就快不少
现在lars bak在搞dart&lt;/p&gt;

&lt;p&gt;大多数人，如果没有经过一定的代码优化理论训练
就算能用c或者汇编写一个hadoop这么大的东西出来
其执行效率还是会低于jvm和hadoop，更不要说开发和维护的效率了&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;分布式是一个非常大的topic，能涵盖你所知道的全部&lt;/dt&gt;
  &lt;dt&gt;我不认为有谁能够一个人搞定全部，这么想的基本上都属于盲目自大的&lt;/dt&gt;
  &lt;dt&gt;所以搞分布式学会利用别人做好的轮子非常重要，否则事倍功半&lt;/dt&gt;
  &lt;dt&gt;有些东西根本不是一个人一天两天能写出来的，比如os, jvm, db这些&lt;/dt&gt;
  &lt;dt&gt;这些都是群策群力多年积累下来的东西，大多数人穷其一生&lt;/dt&gt;
  &lt;dt&gt;能做其中一个，并得到市场的认同&lt;/dt&gt;
  &lt;dt&gt;就牛得不得了了，更不要说上面各种类库，spring, hibernate, hadoop&lt;/dt&gt;
  &lt;dt&gt;这些要是有人能写一个出来，都不要写完整了，你能参与其中&lt;/dt&gt;
  &lt;dt&gt;你就已经很牛了，这些都是apache top level档次的projects&lt;/dt&gt;
  &lt;dt&gt;能做其中一个，做到创始人的话，应该就能在wikipedia上有一个term来描述你的生平&lt;/dt&gt;
  &lt;dt&gt;你这辈子其实不用打工了，到处演讲卖书就好了&lt;/dt&gt;
  &lt;dt&gt;甚至到一些大学里面混个什么荣誉博士，问题不大&lt;/dt&gt;
  &lt;dt&gt;【 在 gtrr35 (GTR-R35) 的大作中提到: 】&lt;/dt&gt;
  &lt;dd&gt;赵老师啊，问你个简单的问题。&lt;/dd&gt;
  &lt;dd&gt;平行计算就是为了效率。既然这么讲求效率，为什么还用java作为平台语言，搞个&lt;/dd&gt;
  &lt;dd&gt;Hadoop？难道不是应该用汇编和C吗？比如用C去implement MPI不就挺好吗？&lt;/dd&gt;
&lt;/dl&gt;

&lt;hr /&gt;
&lt;p&gt;c把跨平台，gc这些常见问题都给搞定了的话，那就是java了
java本身就是c like的语言，跟c++,obj c什么一样，都是c家族
不过可能是唯一一个不把c作为key letter放进去的c like语言
跟python这种非c like语言不太一样
java最早设计出来就是把那些c/c++工程中常见的问题
给统一用一个类库或者环境给搞定，所以最早有说法说是java类库最全最多&lt;/p&gt;

&lt;p&gt;分布式并不是适合数据传递较少，相反，是传递较多才用分布式
但是尽量减少网络的io，是一个常见的优化手段
但是再少，都比并行计算用得多呀，毕竟网络是分布式的一个主要特征
而并行计算不用网络也没啥，弄点共享内存什么的，hpc一样可以搞并行计算&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;小程序没问题，用什么写都有可能，但是一旦项目变大&lt;/dt&gt;
  &lt;dt&gt;再在跨平台gc这种问题上折腾的话，实在是吃不消，力不从心，太累&lt;/dt&gt;
  &lt;dt&gt;大多数时候都是拿个轮子，直接抄来用了，java哲学比较讨人喜欢&lt;/dt&gt;
  &lt;dt&gt;如非万不得已，不要重复造轮子&lt;/dt&gt;
  &lt;dt&gt;【 在 gtrr35 (GTR-R35) 的大作中提到: 】&lt;/dt&gt;
  &lt;dd&gt;收藏了！&lt;/dd&gt;
  &lt;dd&gt;我是把分布式计算和并行计算混为一谈，因为我用到的都是后者。&lt;/dd&gt;
  &lt;dd&gt;按照你的说法，其实分布式计算很适合节点间数据传递较少的任务。对于这些任务，网&lt;/dd&gt;
  &lt;dd&gt;速不一定是瓶颈。比如一个大程序，是同时cpu intensive和memory intensive的，但&lt;/dd&gt;
  &lt;dd&gt;是可以分割，并且每个分割出来的小任务，也都是cpu&amp;amp;memory intensive的，但是同时&lt;/dd&gt;
  &lt;dd&gt;节点间的数据传递有限。这样的任务，网络的latency就不是瓶颈了吧。而且用C也比&lt;/dd&gt;
  &lt;dd&gt;java效率高吧？&lt;/dd&gt;
  &lt;dd&gt;跨平台的确是个问题。要不是有这个问题，肯定现在最流行的是C，并且比第二的语言&lt;/dd&gt;
  &lt;dd&gt;可能高出一个数量的使用度。问个外行话，能不能先在所有的unix和linux系统下先
把C&lt;/dd&gt;
  &lt;dd&gt;跨平台了？&lt;/dd&gt;
&lt;/dl&gt;

&lt;hr /&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://interactivepython.org/runestone/static/pythonds/index.html&quot;&gt;Problem Solving with Algorithms and Data Structures&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.mitbbs.com/article_t1/DataSciences/6829_0_1.html&quot;&gt;zhaoce&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.mitbbs.com/article/JobHunting/32600683_0.html&quot;&gt;Algorithmic&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Python Virtualenv</title>
   <link href="/2015/03/05/python-virtualenv/"/>
   <updated>2015-03-05T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/03/05/python-virtualenv</id>
   <content type="html">
&lt;p&gt;To create isolated Python development environment, each for a specific project.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Install &lt;em&gt;virtualenv&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# emerge -avt dev-python/virtualenv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;dev-python/pip&lt;/em&gt; will be installed as a dependency.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;NEVER&lt;/strong&gt; use &lt;em&gt;pip&lt;/em&gt; to install system-wide packages, which may conflict with Gentoo portage, making the system difficult to maintain.&lt;/p&gt;

    &lt;p&gt;Suppose you &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install foo&lt;/code&gt; and forget installing it through &lt;em&gt;pip&lt;/em&gt;. Later on, you decide to uninstall it by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emerge -avc foo&lt;/code&gt;. You can imagine how horrible that is! Portage &lt;em&gt;emerge&lt;/em&gt; knows nothing about how &lt;em&gt;pip&lt;/em&gt; installed the &lt;em&gt;foo&lt;/em&gt; package, let alone &lt;em&gt;equery&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Use &lt;em&gt;pip&lt;/em&gt; within virtual environment and use &lt;em&gt;emerge&lt;/em&gt; for system-wide packages.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Create &lt;em&gt;virtualenv&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Switch to normal user account:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;virtualenv &lt;span class=&quot;nt&quot;&gt;--help&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;virtualenv &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; python2.7 &lt;span class=&quot;nt&quot;&gt;--system-site-packages&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; ~/workspace/python/venv-test
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ls &lt;/span&gt;workspace/python/venv-test/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;A new directory named &lt;em&gt;venv-test&lt;/em&gt; under &lt;em&gt;~/workspace/python/&lt;/em&gt; is created. The output will be like this:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tux@zhtux ~ $ virtualenv -p python2.7 --system-site-packages -v workspace/python/venv-test
Already using interpreter /usr/bin/python2.7
Creating workspace/python/venv-test/lib/python2.7
Symlinking Python bootstrap modules
  Symlinking workspace/python/venv-test/lib/python2.7/config
  Symlinking workspace/python/venv-test/lib/python2.7/lib-dynload
  Symlinking workspace/python/venv-test/lib64/python2.7/os.py
  Ignoring built-in bootstrap module: posix
  Symlinking workspace/python/venv-test/lib64/python2.7/posixpath.py
  Cannot import bootstrap module: nt
  Symlinking workspace/python/venv-test/lib64/python2.7/ntpath.py
  Symlinking workspace/python/venv-test/lib64/python2.7/genericpath.py
  Symlinking workspace/python/venv-test/lib64/python2.7/fnmatch.py
  Symlinking workspace/python/venv-test/lib64/python2.7/locale.py
  Symlinking workspace/python/venv-test/lib64/python2.7/encodings
  Symlinking workspace/python/venv-test/lib64/python2.7/codecs.py
  Symlinking workspace/python/venv-test/lib64/python2.7/stat.py
  Symlinking workspace/python/venv-test/lib64/python2.7/UserDict.py
  Symlinking workspace/python/venv-test/lib64/python2.7/copy_reg.py
  Symlinking workspace/python/venv-test/lib64/python2.7/types.py
  Symlinking workspace/python/venv-test/lib64/python2.7/re.py
  Symlinking workspace/python/venv-test/lib64/python2.7/sre.py
  Symlinking workspace/python/venv-test/lib64/python2.7/sre_parse.py
  Symlinking workspace/python/venv-test/lib64/python2.7/sre_constants.py
  Symlinking workspace/python/venv-test/lib64/python2.7/sre_compile.py
  Symlinking workspace/python/venv-test/lib64/python2.7/warnings.py
  Symlinking workspace/python/venv-test/lib64/python2.7/linecache.py
  Symlinking workspace/python/venv-test/lib64/python2.7/_abcoll.py
  Symlinking workspace/python/venv-test/lib64/python2.7/abc.py
  Symlinking workspace/python/venv-test/lib64/python2.7/_weakrefset.py
Creating workspace/python/venv-test/lib/python2.7/site-packages
Writing workspace/python/venv-test/lib64/python2.7/site.py
Writing workspace/python/venv-test/lib64/python2.7/orig-prefix.txt
Creating parent directories for workspace/python/venv-test/include
Symlinking workspace/python/venv-test/include/python2.7
Creating workspace/python/venv-test/bin
New python executable in workspace/python/venv-test/bin/python2.7
Changed mode of workspace/python/venv-test/bin/python2.7 to 0755
Also creating executable in workspace/python/venv-test/bin/python
Changed mode of workspace/python/venv-test/bin/python to 0755
Testing executable with workspace/python/venv-test/bin/python2.7 -c &quot;import sys;out=sys.stdout;getattr(out, &quot;buffer&quot;, out).write(sys.prefix.encode(&quot;utf-8&quot;))&quot;
Got sys.prefix result: u&apos;/home/tux/workspace/python/venv-test&apos;
Creating workspace/python/venv-test/lib64/python2.7/distutils
Writing workspace/python/venv-test/lib64/python2.7/distutils/__init__.py
Writing workspace/python/venv-test/lib64/python2.7/distutils/distutils.cfg
Installing setuptools, pip, wheel...
  Ignoring indexes: https://pypi.python.org/simple
  Collecting setuptools
  Collecting pip
  Collecting wheel
  Installing collected packages: setuptools, pip, wheel
  Successfully installed pip-7.1.2 setuptools-18.2 wheel-0.24.0
...Installing setuptools, pip, wheel...done.
Writing workspace/python/venv-test/bin/activate
Writing workspace/python/venv-test/bin/activate.fish
Writing workspace/python/venv-test/bin/activate_this.py
Writing workspace/python/venv-test/bin/activate.csh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;A new &lt;em&gt;python&lt;/em&gt; executable is &lt;em&gt;copied&lt;/em&gt; from system &lt;em&gt;/usr/bin/python&lt;/em&gt; to &lt;em&gt;~/workspace/venv-test/bin/python&lt;/em&gt;, while &lt;em&gt;pip&lt;/em&gt;, &lt;em&gt;setuptools&lt;/em&gt;, &lt;em&gt;wheel&lt;/em&gt; etc. executables are &lt;em&gt;installed&lt;/em&gt; there as well.&lt;/p&gt;

    &lt;p&gt;We can supply many arguments to &lt;em&gt;virtualenv&lt;/em&gt; command to change its default behavior. For example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p python3.4&lt;/code&gt; specifies the desired Python version instead of &lt;em&gt;/usr/bin/python&lt;/em&gt;. By default, global Python packages (i.e. &lt;em&gt;/usr/lib/python2.7/site-packages/&lt;/em&gt;) are beyond &lt;em&gt;virtualenv&lt;/em&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--system-site-packages&lt;/code&gt; argument fix this issue.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Activate&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;source &lt;/span&gt;workspace/python/venv-test/bin/activate
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;python &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;which python pip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Activation of &lt;em&gt;virtualenv&lt;/em&gt; does &lt;em&gt;not&lt;/em&gt; change the current working directory. That is to say, you are not constrained to that newly created directory. The new &lt;em&gt;venv-test&lt;/em&gt; directory just holds virtual environment files.&lt;/p&gt;

    &lt;p&gt;After activation, the created virtual environment name &lt;em&gt;venv-test&lt;/em&gt; will be appended to &lt;em&gt;bash&lt;/em&gt; prompt like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(venv-test)tux@zhtux ~ $&lt;/code&gt;. This indicates and reminds that we are successfully switched to a virtual environment.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;pip install&lt;/p&gt;

    &lt;p&gt;As mentioned, we should not install system-wide packages by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install foobar&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;Pakcages installed within &lt;em&gt;virtualenv&lt;/em&gt; environment are bound to and only meaningful for the very environment! Those packages are placed under &lt;em&gt;~/workspace/python/venv-test/lib/python2.7/site-packages/&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;pip freeze&lt;/p&gt;

    &lt;p&gt;Say, you want to creat a new project, and need to clone the current &lt;em&gt;virtualenv&lt;/em&gt;. The &lt;em&gt;freeze&lt;/em&gt; command helps.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip freeze &amp;gt; requirement.txt&lt;/code&gt; will  create file &lt;em&gt;requirements.txt&lt;/em&gt; that contains a full list of packages within current virtual environment, along with their respective versions.  You can also use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip list &amp;gt; requirement.txt&lt;/code&gt;, but the output format is a little different.&lt;/p&gt;

    &lt;p&gt;Within the new virtual environment, try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install -r requirements.txt&lt;/code&gt; to install the same set of packages. This can help ensure consistency across installations, across deployments, and across developers.&lt;/p&gt;

    &lt;p&gt;&lt;strong&gt;attention&lt;/strong&gt;: if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--system-site-packages&lt;/code&gt; was added, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip freeze/list&lt;/code&gt; includes system-wide Python packages. But don&apos;t worry, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install -r requirements.txt&lt;/code&gt; won&apos;t pull in those packages as long as we stick to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--system-site-packages&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Lastly, remember to exclude the virtual environment directory (i.e. &lt;em&gt;venv-test&lt;/em&gt;) from source control system (i.e. add to *.gitignore).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Deactivate&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;deactivate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Delete&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; workspace/python/venv-test
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Just remove the created directory!&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Run script without actication&lt;/p&gt;

    &lt;p&gt;It&apos;s easy to run script of &lt;em&gt;virtualenv&lt;/em&gt; without activating.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/full/path/to/virtualenv/bin/python foobar.py
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/full/path/to/virtualenv/bin/foobar.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Use &lt;em&gt;full path&lt;/em&gt; to &lt;em&gt;python&lt;/em&gt; or the script within &lt;em&gt;virtualenv&lt;/em&gt;, Python will add &lt;em&gt;/full/path/to/virtualenv/lib/python2.7/site-packages/&lt;/em&gt; to &lt;em&gt;sys.path&lt;/em&gt; automatically. It is handy if we want to invoke the script from GUI. It also helps if we don&apos;t bother activating virtualenv each time.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;As the word implies, &lt;em&gt;virtualenvwrapper&lt;/em&gt; is a wrapper to &lt;em&gt;virtualenv&lt;/em&gt; and helps manage multiple virtual environments. Especially, it places all your virtual environments in one place.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Emacs &lt;a href=&quot;https://github.com/jorgenschaefer/pyvenv&quot;&gt;pyvenv&lt;/a&gt; supports virtual environment. If you installed &lt;a href=&quot;https://github.com/jorgenschaefer/elpy&quot;&gt;elpy&lt;/a&gt;, then it is probably brought in.&lt;/p&gt;

    &lt;p&gt;To activate a virtual environment with Emacs, just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x: pyvenv-activate&lt;/code&gt; and type the relevant directory.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Details
    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;https://virtualenv.pypa.io/en/latest/&quot;&gt;virtualenv&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://docs.python-guide.org/en/latest/dev/virtualenvs/&quot;&gt;virtual environment&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://blog.samuelololol.org/2013/10/how-python-pip-and-virtualenv-go-along.html&quot;&gt;gentoo python pip and virtualenv&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://www.simononsoftware.com/virtualenv-tutorial-part-2/&quot;&gt;Virtualenv Tutorial Part 2&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://iamzed.com/2009/05/07/a-primer-on-virtualenv/&quot;&gt;A Primer on virtualenv&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://showmedo.com/videotutorials/video?name=2910000&amp;amp;fromSeriesID=291&quot;&gt;a useful video&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>LaTeX</title>
   <link href="/2015/02/05/LaTeX/"/>
   <updated>2015-02-05T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/02/05/LaTeX</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#基本概念&quot; id=&quot;markdown-toc-基本概念&quot;&gt;基本概念&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#排版&quot; id=&quot;markdown-toc-排版&quot;&gt;排版&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#中文支持&quot; id=&quot;markdown-toc-中文支持&quot;&gt;中文支持&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#fontspec&quot; id=&quot;markdown-toc-fontspec&quot;&gt;Fontspec&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#cjk&quot; id=&quot;markdown-toc-cjk&quot;&gt;CJK&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#xecjk&quot; id=&quot;markdown-toc-xecjk&quot;&gt;xeCJK&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ctex-package-with-article-class&quot; id=&quot;markdown-toc-ctex-package-with-article-class&quot;&gt;CTeX package with &lt;em&gt;article&lt;/em&gt; class&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ctex-class&quot; id=&quot;markdown-toc-ctex-class&quot;&gt;CTeX class&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#auctex&quot; id=&quot;markdown-toc-auctex&quot;&gt;AUCTex&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;基本概念&quot;&gt;&lt;a href=&quot;https://www.tug.org/levels.html&quot;&gt;基本概念&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;TeX 系统分为 engine 和 format 两大部分。(input) format 是文档的书写格式，engine 是编译文档的程序。&lt;/p&gt;

    &lt;p&gt;最原始的 format 是 plain TeX，升级后的是 LaTeX (LaTeX2e)，更新的是 ConTeXt. Format 实际是一个特殊的 macro package, 扩展 plain TeX, 只不过这个宏包更高级灵活。在 LaTeX 基础上开发出的扩展 包也可“视作 ”一种 format 就数不更数了，如 CTeX format 等。只不过这类 format 太多太杂不成系统，不算入 TeX 核心组件。通常我们只称其为“宏包 macro package/set”。&lt;/p&gt;

    &lt;p&gt;最原始的 egine 是 TeX, 后面发展出 pdfTeX, XeTeX, LuaTeX 各有特色。注意：没有 LaTeX engine 和 ConTeXt engine 的说法，也没有 pdfLaTeX engine.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;发行版里的各种命令最少暗含一种 engine 和 format。特别的，大部分命令都包含 pdfTeX engine （如 &lt;em&gt;xelatex&lt;/em&gt;）, 支持输出 PDF 格式。&lt;/p&gt;

    &lt;p&gt;如果是 plain TeX format, 命令是 &lt;em&gt;*tex&lt;/em&gt;; 如果是 LaTeX format, 命令则是 &lt;em&gt;*latex&lt;/em&gt;. 最原始的 &lt;em&gt;tex&lt;/em&gt; 命令表示用 TeX 引擎编译 plain TeX format。&lt;em&gt;pdftex&lt;/em&gt; 命令表示用 pdfTeX 引擎编译 plain TeX format. &lt;em&gt;pdflatex&lt;/em&gt; 暗含用 pdfTeX 引擎编译 LaTeX format.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;ConTeXt 比较特殊，同时支持多种 engine 和 format, 需要在 source file 里分别指定，但对应的命令是 &lt;em&gt;context&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;排版&quot;&gt;&lt;a href=&quot;https://ctan.org/topic/tut-latex?lang=en&quot;&gt;排版&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;TeX 源文件包含两个部分：文稿内容和排版控制命令。文稿内容就是我们要写的内容，文字、图片、表格、公式及整个文章的章节段落结构等；排版命令如同 CSS 控制 HTML 显示一样，控制样式、字体、分页等呈现的。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;排版控制命令以 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt; 开始：&lt;/p&gt;

    &lt;div class=&quot;language-latex highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\命&lt;/span&gt;令名[可省略的参数]&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;不可省略的参数&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Note that arguments are enclosed in &lt;em&gt;brace&lt;/em&gt;s, options (or optional arguments) are enclosed in &lt;em&gt;bracket&lt;/em&gt;s.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;排版控制命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\begin{document}&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\end{document}&lt;/code&gt; 表示文稿内容 body 的起始与终止。在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\documentclass{}&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\begin{document}&lt;/code&gt; 之间的区域称为“导言区 preamble”可在此区域内放置一些可影响文档全局样式的控制命令。&lt;/p&gt;

    &lt;p&gt;Anything between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\begin{name}&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\end{name}&lt;/code&gt; is called the &lt;em&gt;content&lt;/em&gt; of the &lt;em&gt;environment&lt;/em&gt;. &lt;em&gt;name&lt;/em&gt; would be the name of the environment like &lt;em&gt;document&lt;/em&gt;. The &lt;em&gt;body&lt;/em&gt; of the article is the &lt;em&gt;content&lt;/em&gt; of the &lt;em&gt;document&lt;/em&gt; environment.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Blanks
    &lt;ol&gt;
      &lt;li&gt;Two or more spaces in text are the same as one.&lt;/li&gt;
      &lt;li&gt;A tab or end-of-line character is the same as a space.&lt;/li&gt;
      &lt;li&gt;A blank line indicates the end of a paragraph.&lt;/li&gt;
      &lt;li&gt;Two or more blank lines are the same as one.&lt;/li&gt;
      &lt;li&gt;Spaces at the beginning of a line are ignored.&lt;/li&gt;
      &lt;li&gt;Add thin space (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\,&lt;/code&gt;) or &lt;em&gt;no space&lt;/em&gt; within strings of initials and be consistent.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;There are three lengths.
    &lt;ol&gt;
      &lt;li&gt;&lt;em&gt;hypen&lt;/em&gt;: type this with a single dash like: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;third-world&lt;/code&gt; country&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;en dash&lt;/em&gt;: two dashed used for number ranges (and other things): office hours are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3--4&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;em dash&lt;/em&gt;: three dashes mark an abrupt change in thought or to add emphasis: an aside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;---like this one---&lt;/code&gt; can be distracting.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;当文档非常复杂时，需要多次编译才能生成最终效果，特别是文档内有引用时。&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;中文支持&quot;&gt;&lt;a href=&quot;https://tex.stackexchange.com/a/17637&quot;&gt;中文支持&lt;/a&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;LaTeX format写英文文档；CTeX format 写中文文档。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;CTeX xeCJK/CJK fontspec&lt;/p&gt;

    &lt;p&gt;CTeX 依赖 xeCJK, CJK and/or CCT; xeCJK 又依赖 fontspec. 特别注意，CJK 独立于 fontspec. CTeX 会根据用户选则的 engine 实时调用xeCJK, CJK, CCT 三者之一。特别注意，CJK, xeCJK 和 CCT 三者不可同时使用，每个文档只可选其一。&lt;/p&gt;

    &lt;p&gt;拿 CTeX 文档为例，CTeX format 基于 LaTeX format, 所以要求 &lt;em&gt;*latex&lt;/em&gt; 命令。如果使用了 CJK 包（如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\CJKfamily&lt;/code&gt;），则要 TeX engine 或 pdfTeX engine, 所以选 &lt;em&gt;latex&lt;/em&gt; 或 &lt;em&gt;pdflatex&lt;/em&gt; 命令。如果使用了 xeCJK/fontspec 包（如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\setCJKmainfont&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\setmainfont&lt;/code&gt;），则要 XeTeX engine, 所以选 &lt;em&gt;xelatex&lt;/em&gt; 命令。 &lt;em&gt;xelatex&lt;/em&gt; 暗含 pdfTeX engine，默认输出 PDF, 加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-no-pdf&lt;/code&gt; 参数则输出 DVI.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;CTeX 管中文格式；xeCJK 管中西文字体自动切换、中文标点压缩. fontspec 管全局字体选择。除 老旧的 CJK 外，xeCJK 是专门为支持 XeTeX 而适配。四者中的任何一种都可以直接处理中文排版，但是越底层，越困难，用户需要了解的命令就越多，关键是用户自己设置的格式还不一定美观，所以一般都用 CTeX 宏包。&lt;/li&gt;
  &lt;li&gt;宋、仿宋都可以看作是衬线字体，而楷体、黑体、幼圆可以看作是非衬线字体。&lt;/li&gt;
  &lt;li&gt;No matter CTeX, xeCJK or fontspec is used, they ignore Fontconfig customization like font renaming, alias etc.&lt;/li&gt;
  &lt;li&gt;下面四个样例引用的字体原始名，实际还可以引用字体文件名，具体请参考 CTeX, xeCJK, CJK, 和 fontspec 文档。&lt;/li&gt;
  &lt;li&gt;如果只插入几个汉字，可以用图片的形式，更方便。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;fontspec&quot;&gt;Fontspec&lt;/h2&gt;

&lt;p&gt;Set global fonts to Chinese. 加载 fontspec 宏包后，使用其提供的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\setmainfont&lt;/code&gt; 命令可设定文稿正文中的中文字体。这样英文字符会用中文字体显示，可能效果不是非常好！由于是 fontspec, 所以要 XeTeX engine.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-tex&quot; data-lang=&quot;tex&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;\documentclass&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[11pt,a4paper,portrait]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;article&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;fontspec&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setmainfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Adobe Song Std&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setsansfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Noto Sans S Chinese&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setmonofont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Adobe Fangsong Std&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\XeTeXlinebreaklocale&lt;/span&gt; &quot;zh&quot;
&lt;span class=&quot;k&quot;&gt;\XeTeXlinebreakskip&lt;/span&gt; = 0pt plus 1pt minus 0.1pt

&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[top=1in,bottom=1in,left=1.2in,right=1in]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;geometry&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;\begin{document}&lt;/span&gt;

世界，你好！

下面讲一下 &apos;setmainfont&apos; 与 &apos;setsansfont&apos; 指令中的可省略参数 &apos;BoldFont&apos; 的用法，这个参数是用来指定衬线与非衬线字体在粗体( bold )状态下所使用的字体，这是因为字体可以在常态下经“加粗”后所得到的实际上是另一种字体。对于任意一款计算机字体而言，它不是一个你想怎么变就可以怎么变的东西，如果一款字体在设计的时候就不是粗体，那么是不可能把它变成粗体的，只有用一种设计好的粗体去替换。虽然有一些办法可以让一些字体经过微量平移并叠合后可以得到类似“粗体”的效果，但那是“穷人的粗体”，显示效果很差的。所以，我们不应该把你正在用的这个“宋体”变成“粗”宋体，而必须去找专门的粗宋体来用。如果找不到粗宋体，那就用黑体来代替，本文的排版就是这么做的，&apos;Adobe Heiti Std&apos; 来作为衬线与非衬线的粗体。

&lt;span class=&quot;nt&quot;&gt;\end{document}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;%%% Local Variables:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% mode: latex&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% TeX-master: t&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% End:&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;其中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\setmainfont&lt;/code&gt; 设置 衬线 字体，因为 XeTeX 默认用是的是衬线字体；&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\setsansfont&lt;/code&gt; 设置反衬线字体；&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\setmonofont&lt;/code&gt; 设置的是等宽字体。&lt;em&gt;fontspec&lt;/em&gt; 提供了一个与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\setmainfont&lt;/code&gt; 等价的命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\setromanfont&lt;/code&gt;，这完全是历史缘故，因为以大部分西方人把 Roman 字体当文章正统字体。&lt;/p&gt;

&lt;h2 id=&quot;cjk&quot;&gt;CJK&lt;/h2&gt;

&lt;p&gt;Insert Chinese characters on demand, especially when writing English article.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-tex&quot; data-lang=&quot;tex&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;\part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Insert Chinese&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;part:insert-chinese&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;\begin{CJK*}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;UTF8&lt;span class=&quot;p&quot;&gt;}{&lt;/span&gt;gbsn&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;插入中文&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;\paragraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;CJK 和 CJK* 环境&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 在英文文档里用 CJK 或 CJK* 环境插入
  少量汉字。后者会忽略汉字后面的空格，推荐使用。&lt;span class=&quot;k&quot;&gt;\subparagraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;字体&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  bsmi~字体可能没有，尝试换一个如~gkai,
  ~gbsn~等。&lt;span class=&quot;k&quot;&gt;\subparagraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;xeCJK 更好&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; xeCJK 在处理细节上更好，关键
  是可方便设置中英文字体。用 xeCJK 则不需要特殊环境包裹汉字，只需
  在``导言区&apos;&apos;设置好中英文字体即可。&lt;span class=&quot;k&quot;&gt;\subparagraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;中英文空格&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 我们
  想要的效果是英文字符前后自动加上空格。即使在 &lt;span class=&quot;k&quot;&gt;\TeX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt; 源码里加了空
  格，CJK 会忽略。xeCJK 则会自动处理，但是效果不是非常好。所以我们
  统一用 CJK 的 CJKspace 包，源码里英文后空格会保留，中文后空格依然
  被 CJK* 压缩。还有一个方法是在需要空格的地方用 tilde &lt;span class=&quot;p&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;\sim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;$&lt;/span&gt;.
&lt;span class=&quot;nt&quot;&gt;\end{CJK*}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\part&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\LaTeX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt; Tutorial&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;part:latex-tutorial&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Basics&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;sec:basics&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

how are you?

&lt;span class=&quot;nt&quot;&gt;\end{document}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;%%% Local Variables:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% mode: latex&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% TeX-master: t&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% End:&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the above example, we assume it&apos;s an English article. We insert Chinese on demand by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\begin{CJK*}&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\end{CJK*}&lt;/code&gt;. However, the CJK macro package defines font names (&lt;em&gt;song&lt;/em&gt;, &lt;em&gt;gbsn&lt;/em&gt;, &lt;em&gt;gkai&lt;/em&gt; etc.) under &lt;em&gt;/usr/share/texmf-site/tex/latex/cjk-latex/*/*.fd&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, we should compile CJK format with TeX engin (&lt;em&gt;latex&lt;/em&gt;) and/or pdfTeX engine (&lt;em&gt;pdflatex&lt;/em&gt;). Dunno why XeTeX engine (&lt;em&gt;xelatex&lt;/em&gt;) cannot locate CJK fonts and miss Chinese characters.&lt;/p&gt;

&lt;p&gt;Sometimes, TeX distribution does not bring along CJK fonts, then check &lt;a href=&quot;http://bbs.ctex.org/forum.php?mod=viewthread&amp;amp;tid=47035&quot;&gt;download a copy&lt;/a&gt; or try xeCJK method.&lt;/p&gt;

&lt;h2 id=&quot;xecjk&quot;&gt;&lt;a href=&quot;https://tex.stackexchange.com/a/160042&quot;&gt;xeCJK&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;xeCJK 较 CJK 和 fontspec 的优势是可以分别设中文和英文字体。&lt;/p&gt;

&lt;div class=&quot;language-latex highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;\documentclass&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[11pt,a4paper]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;article&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;syntonly&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%\syntaxonly&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;xeCJK&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;% brings in `fontspec&apos; automatically&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setmainfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Tinos&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;[ &lt;span class=&quot;c&quot;&gt;% search font by filename&lt;/span&gt;
  Path = /opt/fonts/core/Tinos/,
  Extension = .ttf,
  UprightFont = *-Regular,
  BoldFont = *-Bold,
  ItalicFont = *-Italic,
  BoldItalicFont = *-BoldItalic
]
&lt;span class=&quot;k&quot;&gt;\setsansfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;NotoSans&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;[ &lt;span class=&quot;c&quot;&gt;% search by `postscriptname&apos;&lt;/span&gt;
  BoldFont = NotoSans-Bold,
  ItalicFont = NotoSans-Italic,
  BoldItalicFont = NotoSans-BoldItalic  
]
&lt;span class=&quot;k&quot;&gt;\setmonofont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;migu-1m-regular&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;[
  BoldFont = migu-1m-bold
]
&lt;span class=&quot;k&quot;&gt;\setCJKmainfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Adobe Song Std&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;% search by `family&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKsansfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;NotoSansHans-DemiLight&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;[
  BoldFont = NotoSansHans-Bold
]
&lt;span class=&quot;k&quot;&gt;\setCJKmonofont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Adobe Fangsong Std&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;\begin{document}&lt;/span&gt;

How are you?

非常好！

&lt;span class=&quot;nt&quot;&gt;\end{document}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;%%% Local Variables:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% mode: latex&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% TeX-master: t&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% End:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如上分析，xeCJK 依赖 fontspec, 所以要用 XeTeX 引擎。&lt;/p&gt;

&lt;h2 id=&quot;ctex-package-with-article-class&quot;&gt;CTeX package with &lt;em&gt;article&lt;/em&gt; class&lt;/h2&gt;

&lt;p&gt;用的 article 排版，所以英文格式；但 ctex 包支支持中文编译。&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-tex&quot; data-lang=&quot;tex&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;\documentclass&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[11pt,a4paper]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;article&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\usepackage&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[heading = true,UTF8]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;ctex&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;% By default, CTeX on Linux use /usr/share/texmf-dist/tex/latex/ctex/fontset/ctex-fontset-fandol.def&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setmainfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Tinos&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;[ &lt;span class=&quot;c&quot;&gt;% search font by filename&lt;/span&gt;
  Path = /opt/fonts/core/Tinos/,
  Extension = .ttf,
  UprightFont = *-Regular,
  BoldFont = *-Bold,
  ItalicFont = *-Italic,
  BoldItalicFont = *-BoldItalic
]
&lt;span class=&quot;k&quot;&gt;\setsansfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;NotoSans&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;[ &lt;span class=&quot;c&quot;&gt;% search by `postscriptname&apos;&lt;/span&gt;
  BoldFont = NotoSans-Bold,
  ItalicFont = NotoSans-Italic,
  BoldItalicFont = NotoSans-BoldItalic  
]
&lt;span class=&quot;k&quot;&gt;\setmonofont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;migu-1m-regular&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;[
  BoldFont = migu-1m-bold
]
&lt;span class=&quot;k&quot;&gt;\setCJKmainfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Adobe Song Std&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;% search by `family&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKsansfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;NotoSansHans-DemiLight&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;[
  BoldFont = NotoSansHans-Bold
]
&lt;span class=&quot;k&quot;&gt;\setCJKmonofont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Adobe Fangsong Std&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;\begin{document}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\LaTeX&lt;/span&gt;~中文文档模板&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;作者&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\maketitle&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\tableofcontents&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\newpage&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;前言&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

本文测试CTeX~文档类。

&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;正文&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

下面一一看下Fandol~字体效果。

&lt;span class=&quot;k&quot;&gt;\subsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;宋体&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\songti&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;这是Fandol~宋体。看一下效果吧。&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\subsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;楷体&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\kaishu&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;这是Fandol~中文楷书。&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\subsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;黑体&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\heiti&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;这是Fandol~中文黑体字。&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\subsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;仿宋&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\fangsong&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;这是Fandol~仿宋体。&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;后记&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

TeXLive~CTeX~在Linux~上默认用Fandol~字体集，所以我们要在“导言preamble~”部分重新设置默认字体。若实在需要Fandol~字体，用对应的命令。

&lt;span class=&quot;nt&quot;&gt;\end{document}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;%%% Local Variables:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% mode: latex&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% TeX-master: t&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% End:&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;CTeX 指整个宏包集，而 ctex 仅仅是 &lt;em&gt;ctex.sty&lt;/em&gt; 这个宏包。单独导入的 ctex 包并默认不开启章节标题设置功能，需要使用 heading 选项来开启。&lt;/p&gt;

&lt;h2 id=&quot;ctex-class&quot;&gt;CTeX class&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-tex&quot; data-lang=&quot;tex&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;\documentclass&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;[UTF8]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;ctexart&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;% By default, CTeX on Linux use /usr/share/texmf-dist/tex/latex/ctex/fontset/ctex-fontset-fandol.def&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setmainfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Tinos&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setsansfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Noto Sans&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setmonofont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Migu 1M&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKmainfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Adobe Song Std&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKsansfont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Noto Sans S Chinese&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\setCJKmonofont&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;Adobe Fangsong Std&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;\begin{document}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;\LaTeX&lt;/span&gt;~中文文档模板&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;作者&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\maketitle&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;\tableofcontents&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;前言&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

本文测试CTeX~文档类。

&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;正文&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

下面一一看下Fandol~字体效果。

&lt;span class=&quot;k&quot;&gt;\subsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;宋体&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\songti&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;这是Fandol~宋体。看一下效果吧。&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\subsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;楷体&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\kaishu&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;这是Fandol~中文楷书。&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\subsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;黑体&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\heiti&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;这是Fandol~中文黑体字。&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\subsection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;仿宋&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\fangsong&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;这是Fandol~仿宋体。&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;\section&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;后记&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

TeXLive~CTeX~在Linux~上默认用Fandol~字体集，所以我们要在“导言preamble~”部分重新设置默认字体。若实在需要Fandol~字体，用对应的命令。

&lt;span class=&quot;nt&quot;&gt;\end{document}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;%%% Local Variables:&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% mode: latex&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% TeX-master: t&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;%%% End:&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;auctex&quot;&gt;AUCTex&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://cs2.swfc.edu.cn/~wx672/lecture_notes/linux/latex/latex_tutorial.html&quot;&gt;Emacs + LaTeX 快速上手&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://piotrkazmierczak.com/2010/emacs-as-the-ultimate-latex-editor/&quot;&gt;emacs-as-the-ultimate-latex-editor&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Ubuntu and Debian</title>
   <link href="/2015/02/04/ubuntu/"/>
   <updated>2015-02-04T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/02/04/ubuntu</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#dpkg&quot; id=&quot;markdown-toc-dpkg&quot;&gt;dpkg&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#apt-and-apt-get&quot; id=&quot;markdown-toc-apt-and-apt-get&quot;&gt;apt and apt-get&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;dpkg&quot;&gt;dpkg&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;dpkg&lt;/em&gt; interacts with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.deb&lt;/code&gt; binary directly, and is the underlying tool of &lt;a href=&quot;#apt-and-apt-get&quot;&gt;apt-get&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Metadata.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;--info&lt;/span&gt;/-I kong-enterprise-edition_2.8.4.2_all.deb
 new Debian package, version 2.0.
 size 58635042 bytes: control &lt;span class=&quot;nv&quot;&gt;archive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;104837 bytes.
       1 bytes,     0 lines      conffiles
     524 bytes,    12 lines      control
  366935 bytes,  3828 lines      md5sums
     862 bytes,    30 lines   &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;  postinst
 Package: kong-enterprise-edition
 Version: 2.8.4.2
 Section: default
 Priority: extra
 Architecture: all
 Maintainer: Kong Inc. &amp;lt;support@konghq.com&amp;gt;
 Installed-Size: 220993
 Replaces: kong-community-edition, kong-enterprise-edition-fips
 Provides: kong, lapis, luarocks, luarocks-admin
 Depends: ca-certificates, libpcre3, perl, zlib1g-dev, libyaml-0-2
 Conflicts: kong-community-edition, kong-enterprise-edition-fips
 Description: Kong is a distributed gateway &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;APIs and Microservices, focused on high performance and reliability.

&lt;span class=&quot;c&quot;&gt;# all fields&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;--field&lt;/span&gt;/-g kong-enterprise-edition_2.8.4.2_all.deb
Package: kong-enterprise-edition
Version: 2.8.4.2
Section: default
Priority: extra
Architecture: all
Maintainer: Kong Inc. &amp;lt;support@konghq.com&amp;gt;
Installed-Size: 220993
Replaces: kong-community-edition, kong-enterprise-edition-fips
Provides: kong, lapis, luarocks, luarocks-admin
Depends: ca-certificates, libpcre3, perl, zlib1g-dev, libyaml-0-2
Conflicts: kong-community-edition, kong-enterprise-edition-fips
Description: Kong is a distributed gateway &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;APIs and Microservices, focused on high performance and reliability.

&lt;span class=&quot;c&quot;&gt;# specific field&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; kong-enterprise-edition_2.8.4.2_all.deb Version
2.8.4.2

&lt;span class=&quot;c&quot;&gt;# contents of deb file&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;--contents&lt;/span&gt;/-c kong-enterprise-edition_2.8.4.2_all.deb

&lt;span class=&quot;c&quot;&gt;# congents of repo pkg&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;--listfiles&lt;/span&gt;/-L kong-enterprise-edition
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Search installed.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;pkg&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; pkg&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;Status

&lt;span class=&quot;c&quot;&gt;# which package provides the file&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt; /usr/bin/ls
coreutils: /usr/bin/ls
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Install.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;--install&lt;/span&gt; kong-enterprise-edition_2.8.4.2_all.deb
&lt;span class=&quot;c&quot;&gt;# optionally if needs to install depenency&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get update
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nt&quot;&gt;--fix-broken&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kong version

&lt;span class=&quot;c&quot;&gt;# install or upgrade a specific package&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &amp;lt;pkg-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remove.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# keep config and runtime data&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;--remove&lt;/span&gt;/-r &amp;lt;pkg-name&amp;gt;

&lt;span class=&quot;c&quot;&gt;# clean config and runtime data&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;--pruge&lt;/span&gt;/-p &amp;lt;pkg-name&amp;gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get remove &amp;lt;pkg-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;apt-and-apt-get&quot;&gt;apt and apt-get&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;apt&lt;/em&gt; is a user-friendly high-level wrapper of &lt;em&gt;apg-get&lt;/em&gt; and mainly used on Debian system, but please &lt;em&gt;apt-get&lt;/em&gt; is the default on Ubuntu system. Nowadays, both &lt;em&gt;apt&lt;/em&gt; and &lt;em&gt;apt-get&lt;/em&gt; are avaiable on Ubuntu and Debian.&lt;/p&gt;

&lt;p&gt;Search.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;apt list &lt;span class=&quot;nt&quot;&gt;--all-versions&lt;/span&gt; kong-enterprise-edition

&lt;span class=&quot;c&quot;&gt;# search installed&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;apt list &lt;span class=&quot;nt&quot;&gt;--installed&lt;/span&gt; kong-enterprise-edition

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;apt-cache show kong-enterprise-edition | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;V]ersion

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;apt/apt-cache policy kong-enterprise-edition
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Install.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# pathname to deb file&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt/apt-get &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; ./kong-enterprise-edition_2.8.4.2_all.deb

&lt;span class=&quot;c&quot;&gt;# search from repo&lt;/span&gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt/apt-get &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &amp;lt;pkg-name&amp;gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&amp;lt;pkg-version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remove.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt/apt-get remove &amp;lt;pkg-name&amp;gt;

~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt/apt-get autoremove
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>TeXLive 2014 Installation under Ubuntu 14.04</title>
   <link href="/2015/02/03/TeXLive-2014-Ubuntu-Installation/"/>
   <updated>2015-02-03T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/02/03/TeXLive-2014-Ubuntu-Installation</id>
   <content type="html">&lt;p&gt;Unlike the Windows installer, Unix installer leaves many post-installation steps, especially the &quot;fonts&quot; and &quot;Chinese&quot; parts.&lt;/p&gt;

&lt;h1 id=&quot;basics&quot;&gt;Basics&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Go to &lt;a href=&quot;http://tug.org/texlive&quot; title=&quot;TeXLive&quot;&gt;official website&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Download and unpack &lt;em&gt;install-tl.zip&lt;/em&gt; which will show the installler like &lt;em&gt;install-tl-advanced.bat&lt;/em&gt;, &lt;em&gt;install-tl.bat&lt;/em&gt; and &lt;em&gt;install-tl&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;You may found other installer like &lt;em&gt;install-tl-windows.exe&lt;/em&gt; and &lt;em&gt;install-tl-unx.tar.gz&lt;/em&gt;. The former one is only for Windows while the later one is only for Unix system.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo ./install-tl -gui&lt;/code&gt; to install TeXLive for all users. As the expert GUI mode needs &quot;perl:tk&quot; which is not installed. So the installer degrades into text mode.&lt;/li&gt;
  &lt;li&gt;Use the default configuration some of which can be modified through &lt;em&gt;/usr/share/texlive/2014/texmf.cnf&lt;/em&gt; file after installation. Pay attention to the option &quot;Create Symlinks in System directories&quot;. Leave it alone as &quot;NO&quot;.&lt;/li&gt;
  &lt;li&gt;Before the real installation, read the first three chapters of &lt;a href=&quot;http://tug.org/texlive/doc/texlive-en/texlive-en.html&quot;&gt;official documentation&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The while installation process might need one and a half hour. JUST WAIT!&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Environment variables for Unix. Add the following three lines to the end of &lt;em&gt;~/.profile&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PATH=/usr/local/texlive/2014/bin/x86_64-linux:$PATH; export PATH
MANPATH=/usr/local/texlive/2014/texmf-dist/doc/man:$MANPATH; export MANPATH
INFOPATH=/usr/local/texlive/2014/texmf-dist/doc/info:$INFOPATH; export INFOPATH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Environment variables: Global configuration. Add the following line to file &lt;em&gt;/etc/manpath.config&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;MANPATH_MAP /usr/local/texlive/2014/bin/i386-linux /usr/local/texlive/2014/texmf-dist/doc/man
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;System font configuration for XeTEX and LuaTEX. Enable XeTEX and LuaTEX to use fonts shipped with TeXLive.&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Copy &lt;em&gt;/usr/local/texlive/2014/texmf-var/fonts/conf/texlive-fontconfig.conf&quot; to &quot;~/.config/fontconfig/font.conf&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fc-cache -fv&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;&quot;texlive-fontconfig.conf&quot; file specifies the TeXLive fonts locations. Copy this file to home foler as per-user fonts configuration. The official site assumes &lt;em&gt;~/.fonts.conf&lt;/em&gt; as the destination folder, which is depricated! Details please refer to post &lt;a href=&quot;http://askubuntu.com/questions/202389/per-user-fonts-conf-file&quot;&gt;Per user fonts.conf file&lt;/a&gt;. We can find in this post the new single user font configuration file location is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$XDG_CONFIG_HOME/fontconfig/fonts.conf&lt;/code&gt;. For more details, please read the man page by command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man fonts.conf&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;test-the-installation&quot;&gt;Test the Installation&lt;/h2&gt;

&lt;p&gt;Follow the official documentation for system test. Everything works fine except the &quot;Chinese&quot; issue. The current configuration cannot generate Chinese file since &quot;xelatex&quot; use windows fonts as default. We need to install windows fonts in Ubuntu though this is not legal.&lt;/p&gt;

&lt;h1 id=&quot;install-windows-chinese-fonts&quot;&gt;Install Windows Chinese Fonts&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Find the four fonts file from windows &lt;em&gt;simfang.ttf&lt;/em&gt;, &lt;em&gt;simhei.ttf&lt;/em&gt; &lt;em&gt;simkai.ttf&lt;/em&gt; and &lt;em&gt;simsun.ttc&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Make a new folder &quot;winfonts&quot; under home directory and copy the four fonts into it.&lt;/li&gt;
  &lt;li&gt;I want to install this four fonts in home directory for the current user. Most of the tutorial online insall them as system-wide fonts. We can find a line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dir prefix=&quot;xdg&quot;&amp;gt;fonts&amp;lt;/dir&amp;gt;&lt;/code&gt; in file &lt;em&gt;/etc/fonts/fonts.conf&lt;/em&gt;. This line denotes the location for single user fonts file location which is actually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$XDG_DATA_HOME/fonts&lt;/code&gt; = &lt;em&gt;~/.local/share/fonts&lt;/em&gt;. Details refer to &lt;a href=&quot;http://manpages.ubuntu.com/manpages/raring/man5/fonts-conf.5.html&quot;&gt;fonts.conf - Font configuration files&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Create directory *~/.local/share/fonts&quot; and move &quot;winfonts&quot; in step 2 into it.&lt;/li&gt;
  &lt;li&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fc-cache -fv&lt;/code&gt; to update the fonts cache.&lt;/li&gt;
  &lt;li&gt;If the fonts were installed for system-wide users, step 5 will be different. Please refer to &lt;a href=&quot;http://www.cnblogs.com/zhj5chengfeng/p/3251009.html&quot;&gt;Ubuntu 12.04 LTS 中安装 windows 字体&lt;/a&gt; and &lt;a href=&quot;http://kayzhang.com/install-texlive-under-ubuntu/&quot;&gt;Ubuntu 下安装并配置 TeXLive&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The last but most important step. We need to modify file &lt;em&gt;/usr/local/texlive/2014/texmf-dist/tex/latex/ctex/fontset/ctex-xecjk-winfonts.def&lt;/em&gt; content. Because this file determines how engine &lt;em&gt;xelatex&lt;/em&gt; finds the windows fonts installed. There are two ways to modify the file. Mainly focusing on the &quot;KaiTi&quot; and &quot;FangSong&quot; font name issue.
    &lt;ol&gt;
      &lt;li&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fc-list :lang=zh-cn | sort&lt;/code&gt; to see the Chinese fonts file name and fonts name.&lt;/li&gt;
      &lt;li&gt;Change &quot;SIMKAI.TTF&quot; to &quot;KaiTi&quot;, and &quot;SIMFANG.TTF&quot; to &quot;FangSong&quot;. This method helps find Chinese fonts through the &quot;fontconfig&apos; tool in Ubuntu.&lt;/li&gt;
      &lt;li&gt;Change &quot;SIMKAI.TTF&quot; to &quot;simkai.ttf&quot; and &quot;SIMFANG.TTF&quot; to &quot;simfang.ttf&quot;. Add line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OSFONTDIR = ~/.local/share/fonts//;/usr/share/fonts//;/usr/local/share/fonts//&lt;/code&gt; to file &lt;em&gt;/usr/local/texlive/2014/texmf.cnf&lt;/em&gt;. This finds the fonts by fonts file name directly without the help of system &quot;fontconfig&quot; tool. So we need to add a line for &lt;em&gt;OSFONTDIR&lt;/em&gt; in file &quot;texmf.cnf&quot;. Since Ubuntu is case sensitive, so the file names &quot;ctex-xecjk-winfonts.def&quot; should be exactly the same as those in &lt;em&gt;~/.local/share/fonts/winfonts&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;For the second method, there is no need to install the fonts, we can put the fonts file anywhere as long as we define variable &lt;em&gt;OSFONTDIR&lt;/em&gt; correctly. Details refer to &lt;a href=&quot;http://blog.csdn.net/lostaway/article/details/6177486&quot;&gt;ubuntu 10.04 Tex Live 2010 + XeTex + ctex中文配置&lt;/a&gt;, &lt;a href=&quot;https://code.google.com/p/ctex-kit/wiki/UnixFonts&quot;&gt;有关类 Unix 系统下 ctex 宏包的字体问题 &lt;/a&gt;, and &lt;a href=&quot;http://kayzhang.com/install-texlive-under-ubuntu/&quot;&gt;Ubuntu 下安装并配置 TeXLive&lt;/a&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;install-adobe-fonts&quot;&gt;Install Adobe Fonts&lt;/h1&gt;

&lt;p&gt;You may read from several links that &lt;em&gt;xelatex&lt;/em&gt; make use of Adobe Fonts as well. That is right though the default is Windows fonts. We can also install Adobe Fonts with exactly the same method as that of Windows Fonts. Copy Adobe Fonts from Windows System or from the Internet.&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.ubuntu.com/Fonts&quot;&gt;ubuntu fonts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://manpages.ubuntu.com/manpages/raring/man5/fonts-conf.5.html&quot;&gt;fonts.conf&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://askubuntu.com/questions/202389/per-user-fonts-conf-file&quot;&gt;single user fonts.conf&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>TeXLive 2014 Installation under Windows</title>
   <link href="/2015/02/02/TeXLive-2014-Windows-Installation/"/>
   <updated>2015-02-02T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/02/02/TeXLive-2014-Windows-Installation</id>
   <content type="html">&lt;p&gt;This is the details on installing TeXLive 2014 under Windows 8.1.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Go to &lt;a href=&quot;http://tug.org/texlive&quot; title=&quot;TeXLive&quot;&gt;official website&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Download and unpack &lt;em&gt;install-tl.zip&lt;/em&gt; which will show the installler like &lt;em&gt;install-tl-advanced.bat&lt;/em&gt;, &lt;em&gt;install-tl.bat&lt;/em&gt; and &lt;em&gt;install-tl&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;You may found other installer like &lt;em&gt;install-tl-windows.exe&lt;/em&gt; and &lt;em&gt;install-tl-unx.tar.gz&lt;/em&gt;. The former one is only for Windows while the later one is only for Unix system.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Run &lt;em&gt;install-tl-advanced.bat&lt;/em&gt; as administrator to install TeXLive for all users.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use the default configuration except the one &lt;em&gt;texmfhome&lt;/em&gt;. I change it from &lt;em&gt;~\texmf&lt;/em&gt; to &lt;em&gt;E:\texmf&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;If several users in this machine. How to distinguish the different user data under &lt;em&gt;texmfhome&lt;/em&gt; in &lt;em&gt;E:\texmf&lt;/em&gt;?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Before the real installation, read the first three chapters of &lt;a href=&quot;http://tug.org/texlive/doc/texlive-en/texlive-en.html&quot;&gt;official documentation&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The while installation process might need one and a half hour. JUST WAIT!&lt;/li&gt;
  &lt;li&gt;Once finished, read chapter &lt;a href=&quot;http://tug.org/texlive/doc/texlive-en/texlive-en.html#x1-300003.4&quot;&gt;3.4 Post-install actions&lt;/a&gt; and chapter &lt;a href=&quot;http://tug.org/texlive/doc/texlive-en/texlive-en.html#x1-470006&quot;&gt;6 Notes on Windows&lt;/a&gt;. If necessary, you can also read &lt;a href=&quot;http://tug.org/texlive/windows.html&quot;&gt;TeX Live on Windows&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Actually, the installer under Windows is fairly smart to handle everything else. Hence, for step 7, you just need to understand the points.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>AucTeX Emacs</title>
   <link href="/2015/01/30/auctex-emacs/"/>
   <updated>2015-01-30T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/01/30/auctex-emacs</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Let Emacs + AucTeX support LaTeX writing and compiling.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;auctex&quot;&gt;AucTeX&lt;/h1&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;; In order to get support for many of the LaTeX packages you will&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; use in your documents, you should enable document parsing as&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; well, which can be achieved by:&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-auto-save&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-parse-self&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; If you want to make AUCTeX aware of style files and multi-file documents&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; right away, insert the following three lines in your &apos;init.el&apos; file.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;setq-default&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-master&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Default to PDF output&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;setq-default&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-PDF-mode&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; &apos;xetex&apos; as the default engine&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;setq-default&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-engine&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;xetex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;inversereverse-search&quot;&gt;Inverse/Reverse search&lt;/h1&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;; Method to use for enabling forward and inverse search.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; https://www.gnu.org/software/auctex/manual/auctex/I_002fO-Correlation.html&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-source-correlate-method&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;quote&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;synctex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Toggles support for forward and inverse search. Forward search&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; refers to jumping to the place in the previewed document corresponding&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; to where point is located in the document source and inverse search to&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; the other way round.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-source-correlate-mode&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; If TeX-source-correlate-mode is active and a viewer is invoked,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; the default behavior is to ask if a server process should be started.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Set this variable to t if the question should be inhibited and the&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; server should always be started. Set it to nil if the server should&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; never be started. Inverse search will not be available in the latter case.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; YOU&apos;D BEST NOT ENABLE IT BY DEFAULT FOR SECURITY REASON.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-source-correlate-start-server&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;previewer&quot;&gt;Previewer&lt;/h1&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;; Set MuPDF as the default PDF previewer. Now use the default&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Evince instead since it support forward/reverse search.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;system-type&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;gnu/linux&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;progn&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-view-program-list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MuPDF&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;mupdf %s.pdf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;;(setq TeX-view-program-selection &apos;((output-pdf &quot;Evince&quot;)))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; For Emacs + Sumatra on Windows, the inverse search:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;   C:\emacs\bin\emacsclientw.exe +%l &quot;%f&quot;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Add the above line to Sumatra&apos;s settings:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;   File -&amp;gt; Set inverse search command line&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; http://william.famille-blum.org/blog/static.php?page=static081010-000413&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;system-type&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;windows-nt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;progn&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-view-program-list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;quote&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Sumatra PDF&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;\&quot;E:/SumatraPDF/SumatraPDF.exe\&quot; -reuse-instance&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mode-io-correlate&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; -forward-search %b %n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; %o&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-view-program-selection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;quote&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-dvi&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;style-pstricks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;dvips and start&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-dvi&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Yap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-pdf&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Sumatra PDF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-html&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;start&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;My Gentoo system use MuPDF PDF viewer. How to make it the default previewer of AucTeX? Basically, we need to update two variables, which can be achieved by editing &lt;em&gt;init.el&lt;/em&gt; manually or &lt;em&gt;M-x: customize-variable&lt;/em&gt; in frame mini-buffer. The following steps only show you how to manully add viewer.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;TeX-view-program-list&lt;/p&gt;

    &lt;p&gt;This variable is a list of viewers for different output formats. Emacs has default builtin viewers for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.dvi&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pdf&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.ps&lt;/code&gt; etc. For example, the default viewer for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pdf&lt;/code&gt; is Evince. Here I just want to add MuPDF to the list for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pdf&lt;/code&gt; output. MuPDF does &lt;strong&gt;NOT&lt;/strong&gt; support &lt;em&gt;forward&lt;/em&gt; and &lt;em&gt;backward&lt;/em&gt; search while Evince, Ookular etc. do.&lt;/p&gt;

    &lt;p&gt;If manually edit &lt;em&gt;init.el&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-view-program-list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MuPDF&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;mupdf %s.pdf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Use &lt;em&gt;C-c C-v&lt;/em&gt; to preview PDF output.&lt;/p&gt;

    &lt;p&gt;If command line in mini-buffer, first turn on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x tex-mode&lt;/code&gt; or open a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tex&lt;/code&gt; file.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; M-x customize-variable:  will open the builtin variable editor;
 TeX-view-program-list: open variable for edit
 INS: click to add a viewer to the list except the builtin ones
 Name: MuPDF
 Command: mupdf %s.pdf
 C-x C-s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Open the &lt;em&gt;init.el&lt;/em&gt; file, you will find MuPDF is added to the list.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;TeX-view-program-selection&lt;/p&gt;

    &lt;p&gt;This variable defines the exact viewer to choose from &lt;em&gt;TeX-view-program-list&lt;/em&gt; when viewing a specific TeX output format. Similarly, edit by manual or by command line.&lt;/p&gt;

    &lt;p&gt;If manually:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;TeX-view-program-selection&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-pdf&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MuPDF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If command line in mini-buffer:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; M-x customize-variable:  will open the builtin variable editor;
 TeX-view-program-selection: open for edit
 INS DEL Choice: Value Menu Single predicate: Value Menu output-pdf
                Viewer: Value Menu MuPDF
 C-x C-s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;Just locate &lt;em&gt;Viewer&lt;/em&gt; for &lt;em&gt;output-pdf&lt;/em&gt;. Click on &lt;strong&gt;Value Menu&lt;/strong&gt;, you could get a drop list menu, choose &lt;em&gt;MuPDF&lt;/em&gt;. The updated &lt;em&gt;init.el&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;custom-set-variables&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; custom-set-variables was added by Custom.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; If you edit it by hand, you could mess it up, so be careful.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; Your init file should contain only one such instance.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; If there is more than one, they won&apos;t work right.&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TeX-view-program-list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;quote&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MuPDF&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mupdf %s.pdf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TeX-view-program-selection&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;quote&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-dvi&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;style-pstricks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;s&quot;&gt;&quot;dvips and gv&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-dvi&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;xdvi&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-pdf&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MuPDF&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;output-html&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;xdg-open&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;custom-set-faces&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; custom-set-faces was added by Custom.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; If you edit it by hand, you could mess it up, so be careful.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; Your init file should contain only one such instance.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; If there is more than one, they won&apos;t work right.&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;reftex-and-auctex&quot;&gt;RefTeX and AucTeX&lt;/h1&gt;

&lt;p&gt;Since version 24.3 of Emacs, RefTeX is developed exclusively as part of Emacs. So if you want to get the latest version of RefTeX, you should get the latest version of Emacs. (Now outdated versions of the standalone distribution are kept for archeologic purposes on the GNU FTP server.)&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; The following RefTeX lines might be dispensible since AucTeX is installed&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;; through package manager and RefTeX is builtin.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Turn on RefTeX for AUCTeX. Read http://www.gnu.org/s/auctex/manual/reftex/reftex_5.html&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; with AUCTeX LaTeX mode&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;LaTeX-mode-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;turn-on-reftex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; with Emacs latex mode&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;latex-mode-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;turn-on-reftex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Make RefTeX interact with AUCTeX. Read http://www.gnu.org/s/auctex/manual/reftex/AUCTeX_002dRefTeX-Interface.html&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;reftex-plug-into-AUCTeX&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;writing-latex&quot;&gt;Writing LaTeX&lt;/h1&gt;

&lt;p&gt;For a bignner, refer to &lt;a href=&quot;http://jimgray.tk/2015/02/05/LaTeX/&quot;&gt;LaTeX&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;reference&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.gnu.org/software/auctex/manual/auctex/I_002fO-Correlation.html&quot;&gt;4.2.2 Forward and Inverse Search&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://william.famille-blum.org/blog/static081010-000413.html&quot;&gt;Configuring editors with SumatraPDF&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>iptables</title>
   <link href="/2015/01/29/iptables/"/>
   <updated>2015-01-29T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2015/01/29/iptables</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;iptables is a program used to configure and manage the kernels netfilter modules. It basically serves as a firewall to filter network traffic. &lt;a href=&quot;http://drops.wooyun.org/tips/1424&quot;&gt;入门教程，必读！&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;1-abcs&quot;&gt;1 ABCs&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Linux firewall is implemented in kernel by &lt;em&gt;netfilter&lt;/em&gt;. How to interact with kernel &lt;em&gt;netfilter&lt;/em&gt;? Ip[6]tables!&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;iptables&lt;/em&gt; and &lt;em&gt;ip6tables&lt;/em&gt; are used to set up, maintain, and inspect the &lt;em&gt;tables&lt;/em&gt; of IPv4 and IPv6 packet filter &lt;em&gt;rules&lt;/em&gt; in the Linux kernel.  Several different tables may be defined.  Each table contains a number of built-in &lt;em&gt;chains&lt;/em&gt; and may also contain user-defined chains.&lt;/li&gt;
  &lt;li&gt;Each chain is a list of rules which can match a set of packets.  Each rule specifies what to do with a packet that matches.  This is called a &lt;em&gt;target&lt;/em&gt;,  which  may be a jump to a user-defined chain in the same table.&lt;/li&gt;
  &lt;li&gt;A firewall rule specifies criteria for a packet and a target.  If  the packet  does  not  match, the next rule in the chain is examined; if it does match, then the next rule is specified by the value of the target, which  can  be  the  name  of  a user-defined chain, one of the targets described in iptables-extensions(8),  or  one  of  the  special  values ACCEPT, DROP or RETURN.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The schematic diagram:&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/iptables_arch.png&quot; alt=&quot;diagram 1&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/iptables_traverse.jpg&quot; alt=&quot;diagram 2&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/Netfilter-packet-flow.svg&quot; alt=&quot;diagram 3&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Ip[6]tables has different tables namely: &lt;em&gt;filter nat mangle raw&lt;/em&gt; of which &lt;em&gt;filter&lt;/em&gt; is the default one.&lt;/p&gt;

    &lt;p&gt;Each table contains different chains - builtin chains or user-defined chains. You can think of chain as the direction of traffic flows to. Take &lt;em&gt;filter&lt;/em&gt; table for example, it has three builtin chains namely: &lt;em&gt;INPUT FORWARD OUTPUT&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Each chain consists of rules determing action on packets. Ip[6]tables take action based on the first matched rule. If no rules match, use the default &lt;em&gt;policy&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Each rule mainly consists of two parts: criteria and target. Criteria matches packet by different arguments like protocol, port number, interface, state etc. Target is actually the action took on the matched packet. It&apos;s an action instead of of intuitively an object.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;There is a file &lt;em&gt;/etc/services&lt;/em&gt; recording system&apos;s default services/ports.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Launch&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;c&quot;&gt;# rc-sevice ip[6]tables start&lt;/span&gt;
~ &lt;span class=&quot;c&quot;&gt;# rc-update add ip[6]tables default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Without &lt;em&gt;save&lt;/em&gt; first, you cannot &lt;em&gt;start&lt;/em&gt; the service.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Rules backup&lt;/p&gt;

    &lt;p&gt;If you ever configured &lt;em&gt;iptables&lt;/em&gt; before, then save it before any update.  By default, &lt;em&gt;iptables&lt;/em&gt; itself assume its default but simple rules.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# rc-service ip[6]tables save, to /var/lib/ip[6]tables/rules-save by default&lt;/span&gt;
or
&lt;span class=&quot;c&quot;&gt;# ip[6]tables-save &amp;gt; /var/lib/ip[6]tables/rules-save&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# cp /var/lib/ip[6]tables/rules-save /path/to/ip[6]tables-rules-save-backup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Upon exit (i.e. system shutdown/reboot etc), &lt;em&gt;ip[6]tables&lt;/em&gt; will save rules to &lt;em&gt;/var/lib/ip[6]tables/rules-save&lt;/em&gt; automatically (possibly override previous rules).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Restore rule set:&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ip[6]tables-apply -t 60 /path/to/ip[6]tables-rules-save-backup&lt;/span&gt;
or
&lt;span class=&quot;c&quot;&gt;# ip[6]tables-restore &amp;lt; /path/to/ip[6]tables-rules-save-backup&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# ip[6]tables-save &amp;gt; /var/lib/ip[6]tables/rules-save&lt;/span&gt;
or
&lt;span class=&quot;c&quot;&gt;# rc-service ip[6]tables save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;This happens usually if you want to start from scratch by apply a set of rules while discarding all current rules.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;update-rules&quot;&gt;Update rules&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Refer to the 1st reference, it supplies a basic script (say &lt;em&gt;iptables-rules.sh&lt;/em&gt;) for &lt;em&gt;Generating firewall rules for client&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c&quot;&gt;# chmod u+x /path/to/iptables-rules&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# ./path/to/iptables-rules&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# rc-service ip[6]tables save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The contents of &lt;em&gt;iptables-rules.sh&lt;/em&gt; are bash commands to add rules while &lt;em&gt;/var/lib/ip[6]tables/rules-save&lt;/em&gt; are real rules. There is no much syntax difference between commands and rules-ave file. But they do differ in real usage (discussed in &lt;em&gt;ip[6]tables-apply&lt;/em&gt;).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Remove a rule&lt;/p&gt;

    &lt;p&gt;Suppose you have a bunch of rules, but only want to remove one single rule instead of setting from stratch. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-A -D&lt;/code&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # iptables -t nat -A OUTPUT -p TCP --dport 53 -j DNAT --to-destination 127.0.0.1:9053
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Above we &lt;em&gt;-A append&lt;/em&gt; a rule, and how to remove it?&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # iptables -t nat -D OUTPUT -p TCP --dport 53 -j DNAT --to-destination 127.0.0.1:9053
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Just switch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-A&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-D&lt;/code&gt; - delete a rule.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;ip6tables-apply&quot;&gt;&lt;em&gt;ip[6]tables-apply&lt;/em&gt;&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Always update Iptables rules by ip[6]tables-apply instead of terminal command or bash script&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;As mentioned, Iptables automatically save rules to &lt;em&gt;/var/lib/ip[6]tables/rules-save&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;When start again from scratch, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ip[6]tables-apply -t 60 /var/lib/ip[6]tables/rules-ave&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;When updating (-A -D -I etc.), update &lt;em&gt;rules-save&lt;/em&gt; first and then run command again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reason to use &lt;em&gt;ip[6]tables-apply&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It is a wrapper of &lt;em&gt;ip[6]tables-restore&lt;/em&gt; with confirmation.
    &lt;ol&gt;
      &lt;li&gt;If it cuts down network, roll back to previous rule set;&lt;/li&gt;
      &lt;li&gt;If it find no problem, wait for user&apos;s confirmation during &lt;em&gt;-t&lt;/em&gt; timeout;&lt;/li&gt;
      &lt;li&gt;If timeouts, roll back to previous rule set.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Problems of updating rules on terminal:
    &lt;ol&gt;
      &lt;li&gt;If -A -D -I rule, it may obstruct ongoing packets filtering in Iptables.&lt;/li&gt;
      &lt;li&gt;It difficult to overview the whole rule set for adjustting new rule.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;With IPTables rules, order matters&lt;/strong&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So when testing all examples below, convert the command line into &lt;em&gt;rules-save&lt;/em&gt; format. Most of the time, you only need to omit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iptables [-t nat]&lt;/code&gt; part. Don&apos;t worry, &lt;em&gt;ip[6]tables-apply&lt;/em&gt; will roll back if errors found.&lt;/p&gt;

&lt;h1 id=&quot;check&quot;&gt;Check&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;At any time, you can check current rules that &lt;em&gt;ip[6]tables&lt;/em&gt; is using:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # ip[6]tables [-t filter | nat | mangle | raw | security] -S [chain]
 # ip[6]tables [-t filter | nat | mangle | raw | security] -L [chain] -nv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-t&lt;/code&gt; argument is not supplied, then only the &lt;em&gt;filter&lt;/em&gt; table is printed.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;transparent-proxy&quot;&gt;Transparent proxy&lt;/h1&gt;

&lt;p&gt;Some applications (like Bitorrent) do NOT support proxy and others do NOT support your proxy type. For example, &lt;em&gt;ss&lt;/em&gt; is a sock5 proxy, but command line like &lt;em&gt;wget&lt;/em&gt; only supports &lt;em&gt;http&lt;/em&gt; proxy. How to let them connect through &lt;em&gt;ss&lt;/em&gt;?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;proxychain - a package.&lt;/li&gt;
  &lt;li&gt;transparent proxy by ip[6]tables.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Specify rules to force applications&apos; traffic through that proxy! Application does NOT know about this enforcement for it&apos;s carried out in kernel &lt;em&gt;netfilter&lt;/em&gt; directly without its notice. Please refer to &lt;em&gt;transparent proxy&lt;/em&gt; in post &lt;em&gt;tor&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;First you need a proxy already running. Then use Iptables to redirect application traffic to that proxy &lt;em&gt;nat table OUTPUT chian DNAT target&lt;/em&gt;. It&apos;s &lt;em&gt;nat&lt;/em&gt; table instead of other table! &lt;em&gt;nat&lt;/em&gt; table is only consulted on NEW TCP connection. After connection established, no need to and CANNOT DNAT/REDIRECT any more. So we DNAT/REDIRECT in &lt;em&gt;nat&lt;/em&gt; table.&lt;/p&gt;

&lt;p&gt;The difference between DNAT and REDIRECT, refer to &lt;a href=&quot;http://serverfault.com/a/179204&quot;&gt;DNAT vs REDIRECT&lt;/a&gt; and &lt;a href=&quot;http://unix.stackexchange.com/q/144497&quot;&gt;dnat redirect&lt;/a&gt;. According to netfilter documentation, redirection is a specialized case of destination NAT. REDIRECT is equivalent to doing DNAT to the incoming interface (for imcoming traffic including locally generated traffic). Think of DNAT as the case of &lt;em&gt;destination NAT&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Transparent proxy usually plays in two directions: incoming traffic and outgoing traffic.&lt;/p&gt;

&lt;p&gt;For example, you are running a HTTP server at port 2000 while offering access by port 80. Then on your sever, you should REDIRECT incoming traffic from 80 to 2000: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-ports 2000&lt;/code&gt;. If the real HTTP service on another host, then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DNAT --to-destination&lt;/code&gt; instead. Most of time, when handling outgoing traffic, use DNAT since the destination address will be changed.&lt;/p&gt;

&lt;p&gt;For example, your application want to send traffic outside of localhost. But you want to let the traffic go through a proxy first: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner tor -j DNAT --to-destination 127.0.0.1:9040&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To refine the transparent proxy control, you can define personal chain like:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# iptables -t nat -N TRANSPROXY&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner 105 -j TRANSPROXY&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# iptables -t nat -A TRANSPROXY -p tcp -d imap.gmail.com -m tcp --dport 993 -j DNAT --to-destination 127.0.0.1:9040&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There is one issue on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d imap.google.com&lt;/code&gt; part. On the man page:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Please note that specifying any name to be resolved with a remote query such as DNS is a really  bad  idea.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What does that mean? If you specify a hostname instead of an IP address, then Iptables needs DNS resolving before appending the rule. Suppose Iptables was added to system boot script. When reading this rule (from &lt;em&gt;/var/lib/ip[6]tables/rules-save), it will first call DNS to resolve *imap.gmail.com&lt;/em&gt;. Then:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Iptables does not filter packets based on hostnames (DNS is not on TCP or IP layer but above that). Iptables (netfilter in kernel) are based on IPs and ports.&lt;/p&gt;

    &lt;p&gt;Iptables is just userspace tool to interact with kernel. The real firewall is &lt;em&gt;netfilter&lt;/em&gt; in kernel. However, kernel does NOT understand &lt;em&gt;hostname&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When run that terminal command, userspace &lt;em&gt;iptables&lt;/em&gt; will first resolve &lt;em&gt;imapt.gmail.com&lt;/em&gt;. Append the rule by replacing &lt;em&gt;imap.gmail.com&lt;/em&gt; with IP.&lt;/p&gt;

    &lt;p&gt;The real problem is: most services providers use dynamic IPs (by CDN / cache servers). If IP changes, rule will be invalid.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you put the rule in &lt;em&gt;/var/lib/iptables/rules-save&lt;/em&gt; which is the default location for Iptables to save/load rules, it will be a little different.&lt;/p&gt;

    &lt;p&gt;On boot, Iptables load rules from &lt;em&gt;/var/lib/iptables/rules-save&lt;/em&gt; and try resolve &lt;em&gt;imap.gmx.com&lt;/em&gt;. Similarly, this happens when execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iptables-restore&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iptables-apply&lt;/code&gt; by using that path. Issues during boot:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;DNS is called before Iptables is fully launched on boot. Security risk! Any network should occur only after Iptables start.&lt;/li&gt;
      &lt;li&gt;If DNS service is not ready when Iptables loads, then Iptables loading fails.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;Actually, this issue does NOT happen on my Gentoo system. Why? Iptables will automatically save rules to &lt;em&gt;/var/lib/iptables/rules-save&lt;/em&gt; on server stop.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;So put that rule in somewhere else. First, it won&apos;t be overriden by Iptables on service stop. Second, avoid DNS resolve on boot.&lt;/p&gt;

    &lt;p&gt;A compromise proposal is to manually resolve IP. First &lt;em&gt;ping imap.gmail.com&lt;/em&gt; and then use the resolved IP.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Most service provider like Google, Microsoft etc. use CDN / cache servers to dynamically deliver services. IPs vary from time to time. Added rule might be invalid in a few days.&lt;/li&gt;
  &lt;li&gt;In order to make use of custom chain (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-N&lt;/code&gt;), you&apos;ll have to jump (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-j&lt;/code&gt;) to it from somewhere&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A possible solution uses Iptables&apos; &lt;em&gt;string match&lt;/em&gt; module to match hostname instead of specifying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-d hostname&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# iptables -t nat -A OUTPUT -p tcp -m string --string &quot;imap.gmail.com&quot; --algo bm --dport 993 -j DNAT --to-destination 127.0.0.1:2000&lt;/span&gt;
or
&lt;span class=&quot;c&quot;&gt;#iptables -A OUTPUT -p tcp -tcp --tcp-flags SYN -m string --string --algo bm &quot;imap.gmail.com&quot; --dport 993 -j DNAT --to-destination 127.0.0.1:2000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But neither work:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;In 1st example, &lt;em&gt;nat&lt;/em&gt; table is only consulted for new TCP connection (SYN packet without any contents). No hostname string &lt;em&gt;imap.gmail.com&lt;/em&gt; in SYN packet. Connection not established yet for contents delivery.&lt;/li&gt;
  &lt;li&gt;The 2nd example moves to &lt;em&gt;filter&lt;/em&gt; table. But &lt;em&gt;–tcp-flags SYN&lt;/em&gt; has the same issue as 1st. By the way, &lt;em&gt;imap.gmail.com&lt;/em&gt; use SSL connection. The packets conents are encrypted. So we cannot do &lt;em&gt;string&lt;/em&gt; match.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To summary:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Top-down: http/smtp/imap/ftp - ssl (tls)/socks - tcp - ip - link - physical.&lt;/li&gt;
  &lt;li&gt;Iptables works mainly on IP and port.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Only new TCP SYN packet consults &lt;em&gt;nat&lt;/em&gt; table - to establish TCP connection. Established connections bypass &lt;em&gt;nat&lt;/em&gt; table - TCP is a stateful protocol.&lt;/p&gt;

    &lt;p&gt;DNAT/REDIRECT works only on &lt;em&gt;nat&lt;/em&gt; table. In other words, DNAT/REDIRECT interferes during connection establishment. After establishment, there is no need to DNAT/REDIRECT any more.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;string&lt;/em&gt; match:
    &lt;ol&gt;
      &lt;li&gt;Match packet contents. Cannot match strings in &lt;em&gt;nat&lt;/em&gt; table since it&apos;s only consulted by SYN packet without payload. Usually use &lt;em&gt;string&lt;/em&gt; match in &lt;em&gt;filter&lt;/em&gt; table.&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;IMAP SSL encrypts TCP connection. TCP payload is encrypted and even in &lt;em&gt;filter&lt;/em&gt; table, hence you cannot match strings from higher layer IMAP.&lt;/p&gt;

        &lt;p&gt;Hostname &lt;em&gt;imap.gmail.com&lt;/em&gt; is a application layer concept. It&apos;s in IMAP header - encrypted! Cannot match hostname of IMAP SSL.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.gentoo.org/wiki/Iptables&quot;&gt;wiki iptables&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wsgzao.github.io/post/iptables/&quot;&gt;iptables 实践&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Iptables&quot;&gt;arch wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://drops.wooyun.org/tips/1424&quot;&gt;入门教程，必读！&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;www.gentoo-wiki.info/Iptables_port_reference&quot;&gt;wiki ports preference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Git Architecture</title>
   <link href="/2014/11/18/git-architecture/"/>
   <updated>2014-11-18T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/11/18/git-architecture</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#three-components&quot; id=&quot;markdown-toc-three-components&quot;&gt;Three Components&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#ref&quot; id=&quot;markdown-toc-ref&quot;&gt;ref&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#git-commands&quot; id=&quot;markdown-toc-git-commands&quot;&gt;Git Commands&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#diff&quot; id=&quot;markdown-toc-diff&quot;&gt;diff&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#commit&quot; id=&quot;markdown-toc-commit&quot;&gt;commit&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#checkout&quot; id=&quot;markdown-toc-checkout&quot;&gt;checkout&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#committing-with-a-detached-head&quot; id=&quot;markdown-toc-committing-with-a-detached-head&quot;&gt;Committing with a Detached HEAD&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#reset&quot; id=&quot;markdown-toc-reset&quot;&gt;reset&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#merge&quot; id=&quot;markdown-toc-merge&quot;&gt;merge&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#cherry-pick&quot; id=&quot;markdown-toc-cherry-pick&quot;&gt;cherry-pick&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#rebase&quot; id=&quot;markdown-toc-rebase&quot;&gt;rebase&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#git-directory&quot; id=&quot;markdown-toc-git-directory&quot;&gt;.git/ directory&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#a-successful-git-branching-model&quot; id=&quot;markdown-toc-a-successful-git-branching-model&quot;&gt;A successful Git branching model&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#reference&quot; id=&quot;markdown-toc-reference&quot;&gt;Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;three-components&quot;&gt;Three Components&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git2.png&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Basically three components:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;working/local space/directory&lt;/p&gt;

    &lt;p&gt;The files we edit on hard disk.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;stage/index area&lt;/p&gt;

    &lt;p&gt;Temperary place that holds updates from working space and _commit_s the updates to repository.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;commit history&lt;/p&gt;

    &lt;p&gt;Besides local repositories, we also have remote repositories.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;index&lt;/em&gt; and &lt;em&gt;repository&lt;/em&gt; reside under the &lt;em&gt;.git/&lt;/em&gt; directory.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git1.png&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The four commands above copy files between the working directory, the stage, and the history:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add&lt;/code&gt; copies files (at their current state) to the stage area. We call it a &lt;em&gt;staging process&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit&lt;/code&gt; saves a snapshot of the stage area to the history. We call it a &lt;em&gt;committing process&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset -- files&lt;/code&gt; unstages files; that is, it copies files from the history to the stage area, namely reset the stage to the preceding state.&lt;/p&gt;

    &lt;p&gt;Use this command to &quot;undo&quot; a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add&lt;/code&gt;. You can also use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset&lt;/code&gt; alone to unstage everything. It does not affect the working directory or the history. We call it a &lt;em&gt;unstaging process&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout -- files&lt;/code&gt; copies files from the stage area to the working directory. Use this to throw away local changes.&lt;/li&gt;
  &lt;li&gt;We can add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt; option to these commands to interactively choose which files to operate on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add&lt;/code&gt; can not only add files that are not yet known to Git, but files that we have just created. Git takes contents for next &lt;strong&gt;commit NOT from the working directory, but from a special temporary area, called index&lt;/strong&gt;. This allows finer control over what is going to be committed. We can exclude even certain pieces of files from commit (try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add -i&lt;/code&gt;), which helps developers stick to &lt;em&gt;atomic commits principle&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It is also possible to skip the index and updates files directly between the working directory and history.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git7.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -a&lt;/code&gt; is equivalent to running git add on all filenames that already exist in the latest commit, and then running git commit. However, new files we have not told Git about are not affected.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit &amp;lt;files&amp;gt;&lt;/code&gt; does the same thing but only affect files specified on the command line.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout HEAD -- &amp;lt;files&amp;gt;&lt;/code&gt; copies files from the latest commit to &lt;strong&gt;both&lt;/strong&gt; the stage and the working directory. Attention please, there is the HEAD &lt;em&gt;ref&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is a brief summary of the commands mentioned above:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git7.jpg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The figure below will be used as a start point of the following sections.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git8.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;ref&quot;&gt;ref&lt;/h1&gt;

&lt;p&gt;How do we know what is the current state of things? What was the latest commit in the history? To answer that let&apos;s look at &lt;em&gt;ref&lt;/em&gt; (short for &lt;em&gt;reference&lt;/em&gt;) to commits like &lt;em&gt;tag&lt;/em&gt;, &lt;em&gt;head&lt;/em&gt; (&lt;em&gt;branch&lt;/em&gt;), and &lt;em&gt;remote&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Tag is a fixed reference that marks a specific point in commit history, for example &quot;v2.6.29&quot;. On the contrary, &lt;em&gt;head&lt;/em&gt; always moves forward to reflect the lastest commit. When it comes to commit history, we use term &apos;head&apos; more than &apos;branch&apos;. But when we emphasize a module of the project, we use &apos;branch&apos; more often. Read &lt;a href=&quot;https://stackoverflow.com/a/25755777&quot;&gt;How do I create tag with certain commits and push it to origin?&lt;/a&gt; for detailed difference between &lt;em&gt;tag&lt;/em&gt; and &lt;em&gt;head&lt;/em&gt;. Whenever we &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git fetch&lt;/code&gt;, it asks the &lt;em&gt;remote&lt;/em&gt; repository, what heads and tags does it have, downloads missing objects (if any) and stores under &lt;em&gt;.git/refs/remotes&lt;/em&gt;. The remote heads are displayed if we run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git branch -r&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the sake of simplicity, let&apos;s forget about &lt;em&gt;tree&lt;/em&gt; and &lt;em&gt;blob&lt;/em&gt; now, and look at commits illustration:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git3.png&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There are three &lt;em&gt;named head_s above, namely _old&lt;/em&gt;, &lt;em&gt;master&lt;/em&gt;, and &lt;em&gt;stable&lt;/em&gt; representing the latest commits of the three &lt;em&gt;branch_es respectively. Just open _.git/refs/heads&lt;/em&gt; directory to inspect heads.&lt;/p&gt;

&lt;p&gt;But to know what is happening right here, right now? There is a special reference &apos;HEAD&apos; (uppercase). Normally HEAD links to one of the heads as &lt;em&gt;current head&lt;/em&gt; and does not refer to commit directly unless it is told to do so. HEAD serves two major purposes:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git4.png&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;It tells Git which commit to take files from when we &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;checkout&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;When we run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout &amp;lt;ref&amp;gt;&lt;/code&gt;, it makes HEAD point to the ref and extracts files from it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It tells Git where to store new commits.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let&apos;s look at a repo with three commits with one tag (&quot;v2.0&quot;) and one head (&apos;master&apos;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;               HEAD (ref to master)
                |
                v
   a&amp;lt;---b&amp;lt;---c master (ref to commit &apos;c&apos;)
        ^
        |
      tag &apos;v2.0&apos; (ref to commit &apos;b&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When Git creates a new commit &apos;d&apos; whose parent is commit &apos;c&apos;, and then updates branch &apos;master&apos; to point to commit &apos;d&apos;. HEAD still links to &apos;master&apos;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    $ edit; git add; git commit

                    HEAD (ref to master)
                     |
                     v
   a&amp;lt;---b---c&amp;lt;---d master (ref to commit &apos;d&apos;)
        ^
        |
      tag &apos;v2.0&apos; (ref to commit &apos;b&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is sometimes useful to be able to checkout a commit that is not at the tip of any named head, or even to create a new commit that is not referenced by any named head. Let&apos;s look at what happens when we checkout commit &apos;b&apos; (here we show three ways this may be done):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    $ git checkout v2.0
    # -or-
    $ git checkout master^^
    # -or-
    $ git checkout master~2
    # -or-
    $ git checkout &amp;lt;hash-of-b&amp;gt;

       HEAD (ref to commit &apos;b&apos;)
        |
        v
   a&amp;lt;---b&amp;lt;---c&amp;lt;---d master (ref to commit &apos;d&apos;)
        ^
        |
      tag &apos;v2.0&apos; (ref to commit &apos;b&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notice that regardless of which checkout command we use, HEAD now refers directly to commit &apos;b&apos;. This is known as being in &lt;strong&gt;detached HEAD&lt;/strong&gt; state (more details below). This simply means that HEAD refers to a specific commit, as opposed to referring to a named head. Let&apos;s see what happens when we create a commit &apos;e&apos;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    $ &amp;lt;edit&amp;gt;; git add; git commit

      HEAD (ref to commit &apos;e&apos;)
        |
        v
        e
        |
        v
   a&amp;lt;---b&amp;lt;---c&amp;lt;---d master (ref to commit &apos;d&apos;)
        ^
        |
      tag &apos;v2.0&apos; (ref to commit &apos;b&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;HEAD points to commit &apos;e&apos; now. We can add yet another commit in this state:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    $ &amp;lt;edit&amp;gt;; git add; git commit

           HEAD (ref to commit &apos;f&apos;)
             |
             v
        e&amp;lt;---f
        |
        v
   a&amp;lt;---b&amp;lt;---c&amp;lt;---d master (ref to commit &apos;d&apos;)
        ^
        |
      tag &apos;v2.0&apos; (ref to commit &apos;b&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But, let&apos;s look at what happens when we then checkout master:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    $ git checkout master

        e&amp;lt;---f       HEAD (ref to master)
        |              |
        v              v
   a&amp;lt;---b&amp;lt;---c&amp;lt;---d master (ref to commit &apos;d&apos;)
        ^
        |
      tag &apos;v2.0&apos; (ref to commit &apos;b&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is important to realize that at this point nothing refers to commit &apos;f&apos; and it becomes &lt;em&gt;orphaned commits&lt;/em&gt;. Eventually commit &apos;f&apos; and &apos;e&apos; would be deleted by Git &lt;em&gt;garbage collection&lt;/em&gt; process. To preserve the commits, we can create a ref to commit &apos;f&apos; before checking out &apos;master&apos;:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git checkout &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; foo   &amp;lt;1&amp;gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git branch foo        &amp;lt;2&amp;gt;
~ &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git tag foo           &amp;lt;3&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Creates a new branch &apos;foo&apos;, which refers to commit &apos;f&apos;, and then make HEAD link to branch &apos;foo&apos;. In other words, we&apos;ll no longer be in detached HEAD state after this command.&lt;/li&gt;
  &lt;li&gt;Similarly, creates a new branch &apos;foo&apos;, but leaves HEAD detached.&lt;/li&gt;
  &lt;li&gt;Like above, creates a new tag &apos;foo&apos;, leaving HEAD detached.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even after we have moved away from commit &apos;f&apos; without a ref, we can still create a head for it. We must first find out the object name (typically by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt;). For example, to see the last two commits to which HEAD referred, we can use either of these commands:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git reflog &lt;span class=&quot;nt&quot;&gt;-2&lt;/span&gt; HEAD
&lt;span class=&quot;c&quot;&gt;# -or-&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git log &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--abbrev-commit&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--pretty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;oneline &lt;span class=&quot;nt&quot;&gt;-2&lt;/span&gt; HEAD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remember that heads are dynamic refs that move along with new commits. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git log&lt;/code&gt; can show the moving path.&lt;/p&gt;

&lt;h1 id=&quot;git-commands&quot;&gt;Git Commands&lt;/h1&gt;

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

&lt;p&gt;There are various ways to look at differences between commits. Below are some common examples. Any of these commands can optionally take extra filename arguments that limit the differences to the named files.&lt;/p&gt;

&lt;p&gt;Generally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt; shows changes between working directory and staging area, unless a commit is present.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git9.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

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

&lt;p&gt;When you commit, git creates a new commit object using the files from the index and sets the parent to the current commit. It then points the current branch (namely the HEAD) to this new commit. In the image below, the current branch is &apos;master&apos;. Before the command was created, &apos;master&apos; points to &apos;ed489&apos;. Afterwards, a new commit, &apos;f0cec&apos;, and then the &apos;master&apos; ref moved to the new commit.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git10.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Pay attention to the index arrow. Here is another example, a commit occurs on branch &apos;maint&apos;, which was an ancestor of &apos;master&apos;, resulting in &apos;1800b&apos;. Afterwards, &apos;maint&apos; is no longer an ancestor of &apos;master&apos;. To join the two histories, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git merge&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; will help.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git11.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Sometimes a mistake is made when committing, but it is easy to rectify with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit --amend&lt;/code&gt;. When you use this command, git creates a new commit with the same parent as the current commit (would be discarded by garbage collection).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git12.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A fourth case is committing with a detached HEAD, as explained later.&lt;/p&gt;

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

&lt;p&gt;The checkout command is used to copy files from the history or the index to the working directory, and to optionally switch branches.&lt;/p&gt;

&lt;p&gt;When a commit given, it updates both the working directory and the index from the history. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout HEAD~ foo.c&lt;/code&gt; copies &apos;foo.c&apos; from the &apos;HEAD~&apos; commit (the parent of the current commit) to the working directory, and also stages it. If no commit name is given, files are copied from the stage to working directory, without any involvement of the history part.&lt;/p&gt;

&lt;p&gt;Whichever mode is invoked, that the history is left untouched.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git13.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When a filename is not given but the reference is a branch, HEAD is linked to that branch (that is, we &lt;em&gt;switch&lt;/em&gt; to that branch), and then the index and working directory are set to match that branch. Any file that exists in commit &apos;a47c3&apos; is copied; any file that exists in commit &apos;ed489&apos; but not in the new one is deleted; and any file that exists in neither is ignored.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git14.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When a filename is not given and the reference is not a (local) branch (a tag, a remote branch, a SHA-1 ID, or something like &apos;master~3&apos;), we get an anonymous branch, resulting detached HEAD. This is useful for jumping around the history.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git15.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;However, committing works slightly different for a detached HEAD, discussed next.&lt;/p&gt;

&lt;h2 id=&quot;committing-with-a-detached-head&quot;&gt;Committing with a Detached HEAD&lt;/h2&gt;

&lt;p&gt;When HEAD is detached, commits work like normal, except no head ref (think of this as an anonymous branch).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git16.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once you check out something else, say master, the commit is (presumably) no longer referenced by anything else, and gets lost. Note that after the command, there is nothing referencing 2eecb.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git17.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If, on the other hand, you want to save this state, you can create a new named branch using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout -b name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git18.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is already discussed earlier in this post.&lt;/p&gt;

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

&lt;p&gt;The reset command modifies the history by moving the current branch to another position. It is updates the stage from history accordingly.&lt;/p&gt;

&lt;p&gt;If a commit is given with no filenames, the current branch is moved to that commit, and then the stage is updated to match this commit. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--hard&lt;/code&gt; is given, the working directory is also updated. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--soft&lt;/code&gt; is given, neither the stage nor the working directory is updated.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git19.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If a commit is not given, it defaults to HEAD. In this case, the branch is not moved, but the stage (and optionally the working directory, if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--hard&lt;/code&gt; is given) is reset to the contents of the last commit.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git20.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If a filenames (and/or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-p&lt;/code&gt;) is given, only that file is reset.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git21.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

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

&lt;p&gt;A merge creates a new commit that incorporates changes from another branch into the current branch. Before merging, the stage must match the current commit. A trivial case is if the other commit is an ancestor of the current commit, in which case nothing is done.&lt;/p&gt;

&lt;p&gt;Another simple scenario is if the current commit is an ancestor of the other commit, the ref is simply moved forward and the other commit is checked out. This results in a &lt;em&gt;fast-forward merge&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git22.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Otherwise, Git would replay all commits until the head of the other branch. Take the following figure for example, it basically takes the current commit &apos;ed489&apos;, the other commit &apos;33104&apos;, and their common ancestor &apos;b325c&apos;, and performs a three-way merge. A new commit &apos;f8bc5&apos; is created with two parents, namely &apos;33104&apos; and &apos;ed489&apos;. The result is saved to the the stage and working directory.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git23.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;cherry-pick&quot;&gt;cherry-pick&lt;/h2&gt;

&lt;p&gt;The cherry-pick command applies patches of existing commits to the current branch with the while preserving the message.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git24.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It is more of a simplified version of &apos;merge&apos;.&lt;/p&gt;

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

&lt;p&gt;Rebase is similar to merge but operates on branch level. A merge creates a single commit with two parents, leaving a non-linear history, whereas a rebase replays the commits of the current branch onto another, and move the current head there, leaving a linear history. In essence, this is an automated way of performing several cherry-picks in a row.&lt;/p&gt;

&lt;p&gt;The figure below takes all the commits that exist in &apos;topic&apos; but not in &apos;master&apos;, replays them onto &apos;master&apos; and then updates &apos;topic&apos; to the new tip. Note that the old commits will be garbage collected if they are no longer referenced.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git25.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To limit how far back to go, use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--onto&lt;/code&gt; option. The following command replays onto master the most recent commits on the current &apos;topic&apos; since &apos;169a6&apos; (exclusive).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git26.svg&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There is also the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--interactive&lt;/code&gt; option, which allows one to do more complicated things than simply replaying commits, namely dropping, reordering, modifying, and squashing commits. There is no obvious picture to draw for this; see &quot;git-rebase(1)&quot; for more details.&lt;/p&gt;

&lt;h1 id=&quot;git-directory&quot;&gt;.git/ directory&lt;/h1&gt;

&lt;p&gt;There are three kinds of &apos;.git/objects&apos;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;blob for file&lt;/li&gt;
  &lt;li&gt;tree for directory&lt;/li&gt;
  &lt;li&gt;commit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All objects are compressed in binary format, but Git provides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git cat-file -t|-p|-s&lt;/code&gt; command to examine objects.&lt;/p&gt;

&lt;p&gt;The &apos;.git/index&apos; file lists filenames along with the identifier of the associated blob, as well as some other data.&lt;/p&gt;

&lt;p&gt;Commit objects have an additional data type, &lt;em&gt;a tree&lt;/em&gt;, identified by SHA-1 hash too. Trees correspond to directories in the working directory, and contain a list of trees and blobs corresponding to each filename within that directory. Each commit stores the identifier of its top-level tree, which in turn contains all of the blobs and other trees associated with that commit.&lt;/p&gt;

&lt;h1 id=&quot;a-successful-git-branching-model&quot;&gt;A successful Git branching model&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/assets/git27.png&quot; alt=&quot;Git Architecure&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://marklodato.github.io/visual-git-guide/index-en.html&quot;&gt;A Visual Git Reference&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://hades.name/blog/2010/01/28/git-your-friend-not-foe-vol-3-refs-and-index/&quot;&gt;Git Is Your Friend not a Foe Vol. 3: Refs and Index&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://nvie.com/posts/a-successful-git-branching-model/&quot;&gt;A successful Git branching model&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Run VBA Macros on Protected Worksheet UserInterfaceOnly</title>
   <link href="/2014/11/17/excel-vba-userinterfaceonly/"/>
   <updated>2014-11-17T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/11/17/excel-vba-userinterfaceonly</id>
   <content type="html">&lt;p&gt;If you run macros on a protected worksheet which attempt to make changes in the worksheet, you will encounter an error:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Run-time error &apos;1004&apos;: Application-defined or object-defined error&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;goal&quot;&gt;Goal&lt;/h1&gt;

&lt;p&gt;Only allow VBA codes to modify or update the worksheets contents. No user input is allowed any more.&lt;/p&gt;

&lt;h1 id=&quot;unprotect--protect&quot;&gt;Unprotect &amp;amp; Protect&lt;/h1&gt;
&lt;p&gt;One option is to unprotect the worksheet, run the code / macro, and then protect it again, as shown below:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Sheet1.Unprotect Password:=&quot;abc&quot; 
 
&apos;Enter Code / Macro
 
Sheet1.Protect Password:=&quot;abc&quot;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;However, this method has some shortcomings:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If the code encounters an error or gets interrupted, your worksheet will remain unprotected;&lt;/li&gt;
  &lt;li&gt;Your worksheet protection password will be displayed in the vba code (vba projects usually protect worksheet with vba code instead of directly from worksheet menus), unless you protect your VBAProject (in the VB Editor code window) to disallow access or viewing of your code;
    &lt;ul&gt;
      &lt;li&gt;The &lt;em&gt;Fund Stats.xls&lt;/em&gt; indeed is protected in VB Editor code window by password.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You will need to enter this code (ie. unprotect &amp;amp; protect statements) repeatedly in each macro.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;error-handler&quot;&gt;Error Handler&lt;/h1&gt;
&lt;p&gt;To overcome the first shortcoming wherein the worksheet remains unprotected upon the code encountering an error, you can use an ErrorHandler, as shown below:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Sub macroProtect1()

Sheet1.Unprotect Password:=&quot;abc&quot; 
 
	&apos;Enable error-handling routine for any run-time error
	On Error GoTo ErrHandler   
 
	&apos;this code will run irrespective of an error or Error Handler
	Sheet1.Cells(1, 1) = UCase(&quot;hello&quot;)

	&apos;this code will give a run-time error, because of division by zero. The worksheet will remain unprotected in the absence of an Error Handler. 
	Sheet1.Cells(2, 1) = 5 / 0

	&apos;this code will not run, because on encountering the above error, you go directly to the Error Handler 
	Sheet1.Cells(3, 1) = Application.Max(24, 112, 66, 4)

Sheet1.Protect Password:=&quot;abc&quot; 

ErrHandler:
  Sheet1.Protect Password:=&quot;abc&quot; 

End Sub 

Sub macroProtect2()

Sheet1.Unprotect Password:=&quot;abc&quot;
 
	&apos;skip all run-time errors
	On Error Resume Next  
 
	&apos;this code will run irrespective of an error or Error Handler
	Sheet1.Cells(1, 1) = LCase(&quot;HELLO&quot;)

	&apos;this code will give a run-time error, because of division by zero. The worksheet will remain unprotected in the absence of an Error Handler. 
	Sheet1.Cells(2, 1) = 5 / 0

	&apos;this code will run, because on encountering the above error, the code continues execution from next statement, and worksheet remains protected. 
	Sheet1.Cells(3, 1) = Application.Min(24, 112, 66, 4)

Sheet1.Protect Password:=&quot;abc&quot;
 
&apos;Turn off error trapping and re-allow run time errors
On Error GoTo 0  

End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The two error handlers are just examples. I think the first one is better.&lt;/p&gt;

&lt;h3 id=&quot;on-error-statements-explained&quot;&gt;On Error Statements explained:&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;On Error Resume Next&lt;/strong&gt;: Specifies that when a run-time error occurs, control goes to the statement immediately following the statement where the error occurred, and execution continues from that point.&lt;br /&gt;
&lt;strong&gt;The On Error GoTo 0&lt;/strong&gt;: statement turns off error trapping.  It disables enabled error handler in the current procedure and resets it to Nothing.&lt;br /&gt;
&lt;strong&gt;On Error GoTo Line&lt;/strong&gt;: Enables the error-handling routine that starts at the specified Line. The On Error GoTo statement traps all errors, regardless of the exception class.&lt;/p&gt;

&lt;h1 id=&quot;userinterfaceonly-parameter&quot;&gt;UserInterfaceOnly parameter&lt;/h1&gt;
&lt;p&gt;A better way to run macros in a protected worksheet would be to use the UserInterfaceOnly argument in the Protect method, by setting the UserInterfaceOnly argument to True, in the manner: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sheet1.Protect Password:=&quot;abc&quot; , UserInterFaceOnly:=True&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;UserInterFaceOnly argument is an optional argument in the Protect method and its &lt;em&gt;default is False&lt;/em&gt;. Setting the UserInterfaceOnly argument to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; means that the worksheet protection applies &lt;strong&gt;only to the user interface and does not apply to macros&lt;/strong&gt; and this will allow Excel to run all macros in the worksheet. If this argument is omitted, protection applies both to macros and to the user interface. You can use the UserInterfaceOnly argument in a worksheet, at the beginning of the macro, to enable the user interface protection each time the macro is run. See following examples:&lt;/p&gt;

&lt;h3 id=&quot;using-the-userinterfaceonly-argument-in-a-worksheet&quot;&gt;Using the UserInterfaceOnly argument, in a worksheet:&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Sub macroProtect3()

Sheet1.Protect Password:=&quot;abc&quot; , UserInterFaceOnly:=True
 
	&apos;enter code
	Sheet1.Cells(1, 1) = UCase(&quot;hello&quot;)

End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It may be noted that if you apply the Protect method with the UserInterfaceOnly argument set to True to a worksheet and then save the workbook, the entire worksheet (not just the interface) will be fully protected when you reopen the workbook. To re-enable the user interface protection after the workbook is opened, you must again apply the Protect method with UserInterfaceOnly set to True. How to solve this issue?&lt;/p&gt;

&lt;p&gt;To re-enable the user interface protection after the workbook is opened, you can use the &lt;strong&gt;UserInterfaceOnly argument in the Workbook_Open Event&lt;/strong&gt; wherein it gets enabled in all or the specified worksheets, each time the workbook is opened.&lt;/p&gt;

&lt;h3 id=&quot;using-the-userinterfaceonly-argument-in-the-workbook_open-event&quot;&gt;Using the UserInterfaceOnly argument, in the Workbook_Open event:&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;If all worksheets use the same password&lt;/strong&gt;, then set the UserInterfaceOnly argument as true in the Workbook_Open event, as follows. Please note that workbook events code must be placed in the code module for the &lt;strong&gt;ThisWorkbook object&lt;/strong&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Private Sub Workbook_Open()

Dim ws As Worksheet

    For Each ws In ThisWorkbook.Worksheets
    	ws.Protect Password:=&quot;abc&quot;, Contents:=True,  UserInterFaceOnly:=True
    Next ws
 
End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;To enable user interface protection for specified worksheets only&lt;/strong&gt; or if the worksheets have different passwords, set the UserInterfaceOnly argument as true in the Workbook_Open event, as follows.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Private Sub Workbook_Open()

	&apos;enter below statement for each worksheet
	Sheet1.Protect Password:=&quot;abc&quot; , UserInterFaceOnly:=True

	Sheet2.Protect Password:=&quot;def&quot; , UserInterFaceOnly:=True

End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;run-macro-on-protected-worksheet-code-remaining-visible--editable-but-protection-password-hidden&quot;&gt;Run macro on protected worksheet, code remaining visible &amp;amp; editable, but protection password hidden:&lt;/h1&gt;

&lt;p&gt;If you want to run a macro on a protected worksheet, and keep the code visible and editable in the VB editor ie. not to protect the VBA project in the code window with a password; and further you &lt;strong&gt;do not want to disclose or display the password&lt;/strong&gt; (used for worksheet protection) to the user, use the following method.&lt;/p&gt;

&lt;p&gt;If you are using 3 worksheets (say, Sheet1, Sheet2 &amp;amp; Sheet3) in a workbook which are password protected and running macros, insert an additional worksheet (Sheet4).&lt;/p&gt;

&lt;h2 id=&quot;step-1-make-the-sheet4-very-hidden-with-this-code&quot;&gt;Step 1: Make the Sheet4 &lt;strong&gt;very hidden&lt;/strong&gt; with this code:&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Sub hideSheet()
&apos;you can make a worksheet &quot;very hidden&quot; which means that it will not be visible to the user and it can be unhidden only with a VBA code because it does not appear in the unhide list in the interface. A sheet can be made &quot;very hidden&quot; by a single line vba code, or through the VB Editor by selecting the relevant sheet and go to Properties Window: Properties -&amp;gt; Visible -&amp;gt; 2-xlSheetVeryHidden (select).

Worksheets(&quot;Sheet4&quot;).Visible = xlVeryHidden
    
End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;step-2-vba-code-to-unhide-if--when-required-the-very-hidden-sheet4&quot;&gt;Step 2: VBA code to unhide (if &amp;amp; when required) the &quot;very hidden&quot; Sheet4:&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Sub unhideSheet()
&apos;you can enter the password, to unhide this &quot;very hidden&quot; worksheet, in this worksheet itself, which means that the password will need to be remembered separately and will not be visible or accessible till the sheet is unhidden.
&apos;In this &quot;very hidden&quot; worksheet, you can store passwords which protect other worksheets on which you wish to run the macros, and these macros will call the stored password(s) from the &quot;very hidden&quot; worksheet.

Dim pswd As String

    pswd = Cells(1, 1)
    mypass = pswd

    pswdMatch = InputBox(&quot;Enter password to unhide sheet&quot;)

    If pswdMatch = pswd Then
        Worksheets(&quot;Sheet4&quot;).Visible = True
    Else
	Exit Sub
    End If

End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;step-3-run-macro-on-sheet2-which-is-password-protected&quot;&gt;Step 3: Run macro on Sheet2, which is password protected:&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Sub macroProtect()

Dim pswdSheet2 As String
 
&apos;store password to protect Sheet2, in Sheet4.Cells(2, 1)
pswdSheet2 = Sheet4.Cells(2, 1)

	   Sheet2.Protect Password:=pswdSheet2, UserInterFaceOnly:=True

	   &apos;enter code
	   Sheet2.Cells(1, 1) = UCase(&quot;hello&quot;)

End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The 3 steps above will ensure that you run the macro on a protected worksheet (Sheet2), whose password is hidden in Sheet4. And Sheet4 is itself protected and &quot;very hidden&quot;, with its own password too entered &amp;amp; hidden in itself. You will just need to separately remember or note the password of Sheet4 to unhide as per Step2.&lt;/p&gt;

&lt;h1 id=&quot;using-the-userinterfaceonly-argument-to-enable-auto-filter&quot;&gt;Using the UserInterfaceOnly argument to Enable Auto Filter:&lt;/h1&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Sub enableFilterOnProtectedWs1()
&apos;Using UserInterfaceOnly argument with EnableAutoFilter property

With Sheet1
 
&apos;this enables AutoFilter arrows when user-interface-only protection is turned on. This EnableAutoFilter property is not saved with the worksheet or session.
&apos;if you cannot use the code to put AutoFiltering on or off (viz: .AutoFilterMode = False) when user-interface-only protection is turned on, use this EnableAutoFilter property.
.EnableAutoFilter = True

&apos;set userinterfaceonly to True, to protect the user interface, but not macros. If this argument is omitted, protection applies both to macros and to the user interface.
.Protect Password:=&quot;123&quot; , contents:=True, UserInterfaceOnly:=True

&apos;removes any existing Autofilter
.AutoFilterMode = False

&apos;AutoFilter arrows get visible, with a filter criteria
.Range(&quot;A1:B10&quot; ).AutoFilter Field:=1, Criteria1:= &quot;&amp;lt;35&quot; 
 
End With

End Sub


Sub enableFilterOnProtectedWs2()
&apos;enabling AutoFilter arrows when user-interface-only protection is turned on, without using the EnableAutoFilter property.

With Sheet1
&apos;set userinterfaceonly to True, to protect the user interface, but not macros. If this argument is omitted, protection applies both to macros and to the user interface. 
.Protect Password:=&quot;123&quot; , contents:=True, UserInterfaceOnly:=True

 &apos;AutoFilter arrows get visible, with a filter criteria
.Range(&quot;A1:B10&quot; ).AutoFilter
.Range(&quot;A1:B10&quot; ).AutoFilter Field:=1, Criteria1:= &quot;&amp;gt;35&quot; 
 
End With

End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;using-userinterfaceonly-argument-to-allow-grouping&quot;&gt;Using UserInterfaceOnly argument to Allow Grouping:&lt;/h2&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt; 
Sub enableGroupingOnProtectedWs()
&apos;Using UserInterfaceOnly argument to allow grouping on a protected worksheet

With Sheet1
 
&apos;allows grouping on a protected worksheet when user-interface-only protection is turned on. This property is not saved with the worksheet or session.
.EnableOutlining = True

&apos;set userinterfaceonly to True, to protect the user interface, but not macros. If this argument is omitted, protection applies both to macros and to the user interface.
.Protect Password:=&quot;123&quot; , contents:=True, UserInterfaceOnly:=True

&apos;to group rows
Rows(&quot;12:14&quot;).Group

&apos;to ungroup rows
&apos;Rows(&quot;12:14&quot;).Ungroup

End With

End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;worksheetprotect-method&quot;&gt;Worksheet.Protect Method:&lt;/h2&gt;

&lt;p&gt;Worksheet.Protect Method - Protect Method as it applies to the Worksheet Object:&lt;/p&gt;

&lt;p&gt;This method Protects a worksheet so that it cannot be modified. If changes are required to be made to a protected worksheet, it is possible to use the Protect method on a protected worksheet if the password is supplied. Also, another method would be to unprotect the worksheet, make the necessary changes, and then protect the worksheet again.&lt;/p&gt;

&lt;p&gt;Syntax:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expression.Protect(Password, DrawingObjects, Contents, Scenarios, UserInterfaceOnly, AllowFormattingCells, AllowFormattingColumns, AllowFormattingRows, AllowInsertingColumns, AllowInsertingRows, AllowInsertingHyperlinks, AllowDeletingColumns, AllowDeletingRows, AllowSorting, AllowFiltering, AllowUsingPivotTables)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*expression&lt;/em&gt; Required. An expression that returns a Worksheet object.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Password&lt;/em&gt; till &quot;AllowUsingPivotTables&quot; are all Optional Variants, of which &quot;UserInterfaceOnly&quot; has been discussed in detail above. Set the &quot;UserInterfaceOnly&quot; argument to TRUE (default value is False), to protect the user interface, but not macros. If this argument is omitted, protection applies both to macros and to the user interface. This makes it distinct from the other Optional Variants, some of which have been illustrated below.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Sub allowSortingOnProtectedWs()
&apos;Allow sorting option on a protected worksheet (from user interface or with VBA code), without using the UserInterfaceOnly argument.
 
&apos;Sorting can only be performed on unlocked or unprotected cells in a protected worksheet
Sheet1.Unprotect Password:=&quot;abc&quot; 
Sheet1.Range(&quot;G1:H10&quot;).Locked = False
 
&apos;Set the AllowSorting property by using the Protect method arguments. This will allow sorting to be performed on the protected worksheet.
Sheet1.Protect Password:=&quot;abc&quot; , contents:=True, AllowSorting:=True

&apos;sort code
Sheet1.Range(&quot;G1:H10&quot; ).Sort Key1:=Sheet1.Range(&quot;G1&quot; ), Order1:=xlDescending

End Sub
 
 
Sub allowFormattingCellsOnProtectedWs()
&apos;Allow formatting of cells on a protected worksheet (from user interface or with VBA code), without using the UserInterfaceOnly argument.
 
&apos;AllowFormattingCells property is set by using the Protect method arguments. Use of this property allows the user to change all formats, but not to unlock or unhide ranges.
Sheet1.Protect Password:=&quot;123&quot; , AllowFormattingCells:=True

&apos;code to format cells
Sheet1.Range(&quot;G1:H10&quot; ).Font.Bold = True
Sheet1.Range(&quot;A1:B10&quot; ).Font.Color = vbBlue

End Sub
 
 
Sub allowFormattingColumnsRowsOnProtectedWs()
&apos;Allow formatting of columns/rows (ie. whether or not columns/rows can resized) on a protected worksheet (from user interface or with VBA code), without using the UserInterfaceOnly argument.
 
&apos;AllowFormattingColumns &amp;amp; AllowFormattingRows property is set by using the Protect method arguments. Set this property to True to enable columns/rows to be resized when the worksheet is protected. The default value is False.
Sheet1.Protect Password:=&quot;123&quot; , AllowFormattingColumns:=True, AllowFormattingRows:=True

&apos;code to format columns and rows
Sheet1.Columns(2).ColumnWidth = 25
Sheet1.Rows(&quot;4:5&quot; ).RowHeight = 25

End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.globaliconnect.com/excel/index.php?option=com_content&amp;amp;view=article&amp;amp;id=117:run-vba-macros-on-protected-worksheet-unprotect-a-protect-userinterfaceonly-argument-worksheetprotect-method&amp;amp;catid=79&amp;amp;Itemid=475&quot;&gt;Run VBA Macros on Protected Worksheet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/445519/how-do-i-avoid-run-time-error-when-a-worksheet-is-protected-in-ms-excel&quot;&gt;How do I avoid run-time error when a worksheet is protected in MS-Excel?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/125449/how-to-protect-cells-in-excel-but-allow-these-to-be-modified-by-vba-script&quot;&gt;How to protect cells in Excel but allow these to be modified by VBA script&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>iCloud Configuration</title>
   <link href="/2014/11/15/icloud-configuration/"/>
   <updated>2014-11-15T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/11/15/icloud-configuration</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;iCloud supports now Windows system from which photo stream is accessible, that is impossible previously.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;photo-stream&quot;&gt;Photo Stream&lt;/h1&gt;

&lt;p&gt;iCloud supports Photo Stream which represents a center place for photos across diferent devices that now includes Windows PC. Firstly turn on Photo Stream setting on the devices where you would like to upload to and download from Photo Stream.On Windows PC, open the iCloud app, select &lt;em&gt;Photos&lt;/em&gt;, and clikc the &lt;em&gt;Options&lt;/em&gt; on the right. There you can choose to turn on Photo Stream for your Windows PC. Similary on Iphone, in settings, &lt;em&gt;Photos &amp;amp; Camera&lt;/em&gt; or &lt;em&gt;iCloud&lt;/em&gt;, toggle &lt;em&gt;My Photo Stream&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But I prefer to turn off &lt;em&gt;Photo Sharing&lt;/em&gt; option at the same time.&lt;/p&gt;

&lt;p&gt;I found iCloud App on Windows really shit! Unintall it. No users!&lt;/p&gt;

&lt;h1 id=&quot;sync-notes-with-outlook-on-windows&quot;&gt;Sync Notes with Outlook on Windows&lt;/h1&gt;

&lt;p&gt;iOS Notes App is either associated with a iCloud Account or with a iCloud email. If you sync notes with iCloud on your iOS devices, the notes notes accros these devices will be synced. If you turn off notes sync with iCloud on one iOS device, your previously synced notes on that device will be moved the corresponding email account. You can access them from the iCloud email folder naming &quot;Notes&quot;. Any new notes on the iOS device will not be uploaded to the iCloud center. But you can chhoose to sync those notes with Outlook on Windows. Details are as follows:&lt;/p&gt;

&lt;p&gt;On iphone you can sync Notes with iCloud. If you would like to export the notes to your PC as normal files. You should firstly disble the synchronization with iCloud in your phone settings.&lt;/p&gt;

&lt;p&gt;Then connect your iphone to iTunes, click &lt;em&gt;info&lt;/em&gt;, you will find an option called &lt;em&gt;Sync notes with Outlook&lt;/em&gt;. Tick it and click apply! Done.&lt;/p&gt;

&lt;h2 id=&quot;notice&quot;&gt;Notice&lt;/h2&gt;
&lt;p&gt;Use the original synchronizatioin with iCloud. Otherwise it would be crazy to use Apple Apps on Windows.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Scripting Language Explanation</title>
   <link href="/2014/11/13/scripting-language-explanatoin/"/>
   <updated>2014-11-13T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/11/13/scripting-language-explanatoin</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;详细分析脚本语言的特点，脚本语言的和其他语言的关系。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;##特点
1、脚本语言(JavaScript，VBscript等)介于HTML和C,C++,Java,C#等编程语言之间。　HTML通常用于格式化和链接文本。而编程语言通常用于向机器发出一系列复杂的指令。&lt;/p&gt;

&lt;p&gt;2、脚本语言与编程语言也有很多相似地方，其函数与编程语言比较相像一些,其也涉及到变量。与编程语言之间最大的区别是编程语言的语法和规则更为严格和复杂一些.&lt;/p&gt;

&lt;p&gt;3、与程序代码的关系：脚本也是一种语言，其同样由程序代码组成。&lt;/p&gt;

&lt;p&gt;注：脚本语言一般都有相应的脚本引擎来解释执行。 他们一般需要解释器才能运行。Python、JAVASCRIPT,ASP,PHP,PERL,Nuva都是脚本语言。C/C++编译、链接后，可形成独立执行的exe文件。&lt;/p&gt;

&lt;p&gt;4、脚本语言是一种解释性的语言,例如Python、vbscript,javascript,installshield script,ActionScript等等,它不象c\c++等可以编译成二进制代码,以可执行文件的形式存在，脚本语言不需要编译，可以直接用，由解释器来负责解释。&lt;/p&gt;

&lt;p&gt;5、脚本语言一般都是以文本形式存在,类似于一种命令。
举个例子说：如果建立了一个程序,叫aaa.exe，可以打开.aa为扩展名的文件，为.aa文件的编写指定了一套规则(语法)，当别人编写了.aa文件后，自己的程序用这种规则来理解编写人的意图，并作出回应，那么，这一套规则就是脚本语言。&lt;/p&gt;

&lt;p&gt;6、相对于编译型计算机编程语言：用脚本语言开发的程序在执行时，由其所对应的解释器（或称虚拟机）解释执行。系统程序设计语言是被预先编译成机器语言而执行的。脚本语言的主要特征是：程序代码即是脚本程序，亦是最终可执行文件。脚本语言可分为独立型和嵌入型，独立型脚本语言在其执行时完全依赖于解释器，而嵌入型脚本语言通常在编程语言中（如C，C++，VB，Java等）被嵌入使用。&lt;/p&gt;

&lt;p&gt;7、和系统程序设计语言相比：不同是脚本语言是被解释而系统程序设计语言是被编译。被解释的语言由于没有编译时间而提供快速的转换，通过允许用户运行时编写应用程序，而不需要耗时的编译/打包过程。解释器使应用程序更加灵活，脚本语言的代码能够被实时生成和执行。脚本语言通常都有简单、易学、易用的特性，目的就是希望能让程序设计师快速完成程序的编写工作。&lt;/p&gt;

&lt;p&gt;##优缺点
&lt;strong&gt;优点&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;快速开发：脚本语言极大地简化了“开发、部署、测试和调试”的周期过程。&lt;/p&gt;

&lt;p&gt;容易部署：大多数脚本语言都能够随时部署，而不需要耗时的编译/打包过程。&lt;/p&gt;

&lt;p&gt;同已有技术的集成：脚本语言被Java或者COM这样的组件技术所包围，因此能够有效地利用代码。&lt;/p&gt;

&lt;p&gt;易学易用：很多脚本语言的技术要求通常要低一些，因此能够更容易地找到大量合适的技术人员。&lt;/p&gt;

&lt;p&gt;动态代码：脚本语言的代码能够被实时生成和执行，这是一项高级特性，在某些应用程序里（例如JavaScript里的动态类型）是很有用也是必需的。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;脚本语言不够全面：它们会要求一门“真正的”编程语言的存在，必须找一个数据库驱动程序将其内置进脚本语言里。&lt;/p&gt;

&lt;p&gt;脚本语言并不是软件工程和构建代码结构的最佳选择，例如面向对象和基于组件的开发。&lt;/p&gt;

&lt;p&gt;脚本语言通常不是“通用”语言，但是能够根据专门的应用来调整，例如：PHP和万维网。&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href=&quot;http://blog.csdn.net/universsky/article/details/8960359&quot;&gt;脚本语言介绍&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>VBS Comprehension</title>
   <link href="/2014/11/12/vbs-comprehension/"/>
   <updated>2014-11-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/11/12/vbs-comprehension</id>
   <content type="html">&lt;p&gt;VBScript是Visual Basic Script的简称，即 Visual Basic 描述语言，有时也被缩写为VBS。VBScript是微软开发的一种脚本语言，可以看作是VB语言的简化版，与VBA的关系也非常密切。它具有原语言容易学习的特性。目前这种语言广泛应用于网页和ASP程序制作，同时还可以直接作为一个可执行程序。用于调试简单的VB语句非常方便。
由于VBScript可以通过Windows脚本宿主调用COM，因而可以使用Windows操作系统中可以被使用的程序库，比如它可以使用Microsoft Office的库，尤其是使用Microsoft Access和Microsoft SQL Server的程序库，当然它也可以使用其它程序和操作系统本身的库。&lt;/p&gt;

&lt;p&gt;在实践中VBScript一般被用在以下&lt;em&gt;三个方面&lt;/em&gt;：&lt;/p&gt;

&lt;p&gt;##Windows操作系统
  VBScript可以被用来自动地完成重复性的Windows操作系统任务。在Windows操作系统中，VBScript可以在Windows Script Host的范围内运行。Windows操作系统可以自动辨认和执行&lt;em&gt;.VBS和&lt;/em&gt;.WSF两种文件格式，此外Internet Explorer可以执行HTA和CHM文件格式。VBS和WSF文件完全是文字式的，它们只能通过少数几种对话窗口与用户通讯。HTA和CHM文件使用HTML格式，它们的程序码可以象HTML一样被编辑和检查。在WSF、HTA和CHM文件中VBScript和JavaScript的程序码可以任意混合。HTA文件实际上是加有VBS、JavaScript成分的HTML文件。CHM文件是一种在线帮助，用户可以使用专门的编辑程序将HTML程序编辑为CHM。&lt;/p&gt;

&lt;p&gt;##网页浏览器（客户方的VBS） 
  网页中的VBS可以用来指挥客户方的网页浏览器（浏览器执行VBS程序）。VBS与JavaScript在这一方面是竞争者，它们可以用来实现动态HTML，甚至可以将整个程序结合到网页中来。至今为止VBS在客户方面未能占优势，因为它只获得因为它只获得Microsoft Internet Explorer的支持（Mozilla Suite可以通过装置一个外挂来支持VBS）。而JavaScript则受到所有网页浏览器的支持。在Internet Explorer中VBS和JavaScript使用同样的权限，它们只能有限地使用Windows操作系统中的对象。&lt;/p&gt;

&lt;p&gt;##网页服务器（服务器方面的VBS）
  在网页服务器方面VBS是微软的Active Server Pages的一部分，它与JavaServer Pages和PHP是竞争对手。在这里VBS的程序码直接嵌入到HTML页内，这样的网页以ASP结尾。网页服务器Internet信息服务执行ASP页内的程序部分并将其结果转化为HTML传递给网页浏览器供用户使用。这样服务器可以进行数据库闻讯并将其结果放到HTML网页中。&lt;/p&gt;

&lt;p&gt;##VBScript主要的优点&lt;/p&gt;

&lt;p&gt;由于VBScript由操作系统，而不是由网页浏览器解释，它的文件比较小、易学。&lt;/p&gt;

&lt;p&gt;在所有2000 / 98SE以后的Windows版本都可直接使用。&lt;/p&gt;

&lt;p&gt;可以使用其它程序和可使用的物件（尤其Microsoft Office）。&lt;/p&gt;

&lt;p&gt;##缺点&lt;/p&gt;

&lt;p&gt;现在VBS无法作为电子邮件的附件了。Microsoft Outlook拒绝接受VBS为附件，收信人无法直接使用VBS附件。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://phplens.com/phpeverywhere/node/view/30&quot;&gt;PHP, Javascript and VBScript Language Summary&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.cnblogs.com/BeyondTechnology/archive/2011/01/09/1931508.html&quot;&gt;VBScript是什么？有什么优缺点？&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</content>
 </entry>
 
 <entry>
   <title>Deadlifts</title>
   <link href="/2014/10/10/fitness-deadlift/"/>
   <updated>2014-10-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/10/10/fitness-deadlift</id>
   <content type="html">&lt;p&gt;Deadlifts are one of the best exercises out there to build your back but it&apos;s easy to make these 5 mistakes. In this video we&apos;ll show you what common Deadlift mistakes to avoid.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Improper Arm, Shoulder and Hip Movement&lt;/li&gt;
  &lt;li&gt;Wrong Exercise (Doing Romanian Deadlifts)&lt;/li&gt;
  &lt;li&gt;Hips Too Low&lt;/li&gt;
  &lt;li&gt;Rounding Your Back&lt;/li&gt;
  &lt;li&gt;Relying on Lifting Gear&lt;/li&gt;
&lt;/ol&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;//www.youtube.com/embed/MDuXuUg15mk&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;How to perform deadlift:&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;//www.youtube.com/embed/-4qRntuXBSc&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>Emacs installation</title>
   <link href="/2014/09/14/emacs-installation/"/>
   <updated>2014-09-14T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/09/14/emacs-installation</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#linux-安装&quot; id=&quot;markdown-toc-linux-安装&quot;&gt;Linux 安装&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#输入法&quot; id=&quot;markdown-toc-输入法&quot;&gt;输入法&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#emacs-启动太慢&quot; id=&quot;markdown-toc-emacs-启动太慢&quot;&gt;Emacs 启动太慢&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#emacs-23-之前的版本&quot; id=&quot;markdown-toc-emacs-23-之前的版本&quot;&gt;Emacs 23 之前的版本：&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#emacs-23-开始的版本&quot; id=&quot;markdown-toc-emacs-23-开始的版本&quot;&gt;Emacs 23 开始的版本&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#eamcsclient&quot; id=&quot;markdown-toc-eamcsclient&quot;&gt;eamcsclient&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#终端下运行-emacsclient&quot; id=&quot;markdown-toc-终端下运行-emacsclient&quot;&gt;终端下运行 emacsclient&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#桌面下运行-emacsclient&quot; id=&quot;markdown-toc-桌面下运行-emacsclient&quot;&gt;桌面下运行 emacsclient&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#windows-10-安装&quot; id=&quot;markdown-toc-windows-10-安装&quot;&gt;Windows 10 安装&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;linux-安装&quot;&gt;Linux 安装&lt;/h1&gt;

&lt;p&gt;下面关于 Linux 的部分主要以 Gentoo 为主。&lt;/p&gt;

&lt;h2 id=&quot;输入法&quot;&gt;输入法&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;确保系统安装 adobe-75dpi 和 adobe-100dpi 字体。&lt;/li&gt;
  &lt;li&gt;如果是 Awesome, 则要把 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LC_CTYPE&lt;/code&gt; 要设置称 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zh_CN.UTF-8&lt;/code&gt;. 如果是 KDE 这样的 DE, 则不用。&lt;/li&gt;
  &lt;li&gt;安装 Fcitx 输入法。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;参考 &lt;a href=&quot;/2015/03/25/gentoo-installation/&quot;&gt;Gentoo Installation&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;emacs-启动太慢&quot;&gt;Emacs 启动太慢&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Emacs = Emacs Makes A Computer Slow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Emacs 由于要加载好多脚本，特别是 .emacs 或 init.el 里的内容很多时，太慢，是 Emacs 一大诟病。不过我们可以利用 Emacs 的 C/S 模式，脚本的加载让 daemon/server 来完成。然后再用客户端 emacsclient 连接 daemon/server，方法如下：&lt;/p&gt;

&lt;h3 id=&quot;emacs-23-之前的版本&quot;&gt;Emacs 23 之前的版本：&lt;/h3&gt;

&lt;p&gt;可以在启动 Emacs 的时候，顺便选择开启 server-start。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;一种方法是在 init.el 里面设定加入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(server-start)&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(server-mode)&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;另一种是直接在 Emacs 的 mini-buffer 输入命令&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x: server-start/server-mode&lt;/code&gt;。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Emacs 23 之前的那种方法有个缺点，即所开启的 server mode 只属于当前的 Emacs frame，如果这个 frame 关闭了，那么 server 就随之关闭。再运行 Eamcs 时，又要重新加载 server mode。所以为了能够利用这个 C/S 模式，开启 server mode 的那个 frame/instance/session 不能关闭！ 只能在另一个 terminal 启动 emacsclient 来链接复用这个 server。&lt;/p&gt;

&lt;h3 id=&quot;emacs-23-开始的版本&quot;&gt;Emacs 23 开始的版本&lt;/h3&gt;

&lt;p&gt;幸好 Emacs 23 引入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emacs --daemon&lt;/code&gt;，那么 daemon 与 server 有细微区别，可以常驻系统（内存）中，与某个 Emacs frame/instance 无关。关闭当前的 Emacs frame，daemon 服务依然存在，这时关闭的仅仅是 client 端。&lt;/p&gt;

&lt;p&gt;下面开始不区分 server 和 daemon 两个词汇。看看 client 端如何链接 daemon/server。&lt;/p&gt;

&lt;h3 id=&quot;eamcsclient&quot;&gt;eamcsclient&lt;/h3&gt;

&lt;p&gt;运行客户端&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;emacsclient&lt;/code&gt;，连接 daemon/server，对文件进行处理。eamcsclient有几个关键参数：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;-t&lt;/p&gt;

    &lt;p&gt;-t 表示在 Terminal 中打开字符界面的 frame.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;-c&lt;/p&gt;

    &lt;p&gt;-c 表示创建 create 一个 X11 界面的 frame，也就是通常所说的 GUI.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;-n&lt;/p&gt;

    &lt;p&gt;-n 表示不必等待 Emacs 结束，立即返回。譬如在命令行运行 emcasclient，默认当前 Terminal 被 Emacs 占用，无法干别的事情。加上 -n 后，Emacs 创建 frame 后立马释放 Termial，你可以继续使用 Terminal。一般 -n 和 -c 相结合使用。注意，-a 和 -n 没有意义。&lt;/p&gt;

    &lt;p&gt;注意，如果开启了 -n，那些需要等待 Emacs 结束的主调用程序就无法正常工作了。譬如，git commit 默认调用系统 EDITOR 或者它自己的 core.editor，如果设置成了下面的 ecx 或者 emc，那么用户无法输入 commit 信息，Emacs已经立马返回了，无法 commit. 所以要为这类程序单独设置一个不带 -n 的小脚本。&lt;/p&gt;

    &lt;p&gt;另外，没有 -n 时，C-x # 会自动关闭 buffer，但是开了 -n 后，就不用 C-x # 了，而是直接 C-x k 或 C-x 5 0.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;-a&lt;/p&gt;

    &lt;p&gt;-a, –alternate-editor=, 表示如果 server mode 没有开启，那么选择一个替代编辑器，譬如 vim/gedit 等。&lt;/p&gt;

    &lt;p&gt;通常我们设置成空：&quot;&quot;。如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-a &quot;&quot;&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--alternate-editor=&quot;&quot;&lt;/code&gt;。设置成空表示，如果 server mode 没有加载（通常是开机第一次运行），由于替代编辑器为空，emacsclient 则会先加载 server。&lt;/p&gt;

    &lt;p&gt;但是如果每次运行 emacsclient 命令时，都带上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-a&lt;/code&gt; 很麻烦。更好的办法是设置系统变量 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ALTERNATE_EDITOR=&quot;&quot;&lt;/code&gt;,下面会涉及到。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;终端下运行-emacsclient&quot;&gt;终端下运行 emacsclient&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;_$_ emacs --daemon
_$_ emacsclient -t -a &quot;&quot; [file names]
_$_ emacsclient -nc -a &quot;&quot; [file names]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里 file names 是可省略的参数。如果每次都这样运行，输入的命令太长来，作如下改进：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;emacs –daemon 可以加入 default runlevel，开机启动。不过我不认为这样是个好主意，毕竟不是每次开机都铁定运行 Emacs，而且还影响开机速度。我们按需启动 Emacs server。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;给这几个命令取别名，或创建脚本，简化命令的长度。脚本文件放在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/bin&lt;/code&gt; 下：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # /usr/local/bin/ect
 #! /bin/bash
 emacsclient -t -a &quot;&quot; &quot;$@&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # /usr/local/bin/ecx
 #! /bin/bash
 emacsclient -nc -a &quot;&quot; &quot;$@&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;$@&quot;&lt;/code&gt; 表示接受命令行的所有参数，主要就是要编辑的文件名列表。默认情况下，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/bin&lt;/code&gt; 已经加入到了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt; 中：&lt;/p&gt;

    &lt;blockquote&gt;
      &lt;p&gt;$ type ecx ect&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;blockquote&gt;
      &lt;p&gt;$ ect/ecx [file names]&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;还有一个更好的脚本 /usr/local/bin/emc，同时支持 ect 和 ecx&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

 &lt;span class=&quot;c&quot;&gt;# The &apos;-n --no-wait&apos; argument:&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;#   returns immediately without waiting for you to &apos;finish&apos; the buffer in Emacs&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# For example, if the script is ran in terminal, after creating the GUI frame,&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# the terminal is relased immediately&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# This script should not be used as an external editor to other programs. For example,&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# git commit waits for the editor before continuation&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# If the system default &apos;EDITOR&apos; is set to this script, you should explicitly specify&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# another editor for those programs like &apos;nano&apos; or &apos;ect&apos;&lt;/span&gt;

 &lt;span class=&quot;c&quot;&gt;# Simple script&lt;/span&gt;

 &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$DISPLAY&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
     &lt;/span&gt;emacsclient &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-nc&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;else
     &lt;/span&gt;emacsclient &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

 &lt;span class=&quot;c&quot;&gt;# Complex script&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# Suppose &apos;DISPLAY&apos; not set properly&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# (fboundp &apos;&quot;&apos;&quot;&apos;tool-bar-mode) is to check whether Emacs&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# is built with GUI support which are uncommon&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# To simplify things, use the simple method above&lt;/span&gt;

 &lt;span class=&quot;c&quot;&gt;# if [ -z &quot;$DISPLAY&quot; ]; then&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;#     IS_GRAPHICAL=true&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# else&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;#     IS_GRAPHICAL=$(emacs --batch -Q --eval=&apos;(if (fboundp &apos;&quot;&apos;&quot;&apos;tool-bar-mode) (message &quot;true&quot;) (message &quot;false&quot;))&apos; 2&amp;gt;&amp;amp;1)&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# fi&lt;/span&gt;

 &lt;span class=&quot;c&quot;&gt;# if $IS_GRAPHICAL; then&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;#     emacsclient -a &quot;&quot; -nc &quot;$@&quot;&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# else&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;#     emacsclient -a &quot;&quot; -t &quot;$@&quot;&lt;/span&gt;
 &lt;span class=&quot;c&quot;&gt;# fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;为了省略脚本中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-a&lt;/code&gt; 参数,在 &lt;em&gt;/etc/env.d/&lt;/em&gt; 下创建文件 &lt;em&gt;99local&lt;/em&gt;，用于存放 system-wide environment variable，内容如下：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; export ALTERNATE_EDITOR=&quot;&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;修改默认编辑器为 ect。在 &lt;em&gt;/etc/env.d/99editor&lt;/em&gt; 添加：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; EDITOR=/usr/local/bin/ect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;这种直接编辑 &lt;em&gt;99editor&lt;/em&gt; 的方法不方便！在 root 下运行:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; # eselect editor list
 # eselect editor set &quot;/usr/local/bin/ect&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;如果是在普通用户下运行 eselect 则设置只对当前用户生效。&lt;/p&gt;

    &lt;p&gt;注：不建议修改系统默认编辑器为 Emacs，默认的轻量级 nano 就非常好。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;# env-update &amp;amp;&amp;amp; source /etc/profile&lt;/p&gt;

    &lt;p&gt;更新系统环境变量，让上面两步生效！&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;上面的步骤是为 system-wide 设置的，也可以单独为用户自己设置 private owned scripts：
    &lt;ol&gt;
      &lt;li&gt;脚本放在 &lt;em&gt;~/bin&lt;/em&gt; 下面。&lt;/li&gt;
      &lt;li&gt;&lt;em&gt;~/bin&lt;/em&gt; 加入到当前用户的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt; 中。&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ALTERNATE_EDITOR&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EDITOR&lt;/code&gt; 相应设置在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt; 中。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;桌面下运行-emacsclient&quot;&gt;桌面下运行 emacsclient&lt;/h3&gt;

&lt;p&gt;上面的步骤是针对命令行来的,对于 Gentoo 下的 XFCE 桌面环境,该如何办启动 emacsclient?&lt;/p&gt;

&lt;p&gt;修改 &lt;em&gt;/usr/share/applications/emacsclient.desktop&lt;/em&gt; 文件. Gentoo 安装 Emacs 时,默认创建了 emacsclient.desktop 文件,但是在 XFCE 菜单里没有出现. 我们参考 emacs.desktop 文件，需要修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NoDisplay&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exec&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Categories&lt;/code&gt; 参数:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;NoDisplay=false&lt;/p&gt;

  &lt;p&gt;Exec=/usr/bin/emacsclient -nc -a &quot;&quot; %F&lt;/p&gt;

  &lt;p&gt;Categories=Development;TextEditor;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;如果在前面的 &lt;em&gt;99local&lt;/em&gt; 里设置了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ALTERNATE_EDITOR&lt;/code&gt;，这里面的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-a&lt;/code&gt; 参数也可以省略掉。一个更好的编辑 emacsclient.desktop 文件办法是直接：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# pushd /usr/share/applications
# mv emacs.desktop emacsclient.desktop 然后依照上面修改里面的 `Exec` 那一行即可。这里，我们去掉了默认的 Emacs GUI 启动菜单。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中有个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%F&lt;/code&gt; 参数，具体意义参考 &lt;a href=&quot;http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html&quot;&gt;Desktop Entry Specification&lt;/a&gt;。注意这个参数不能放在 Terminal 启动脚本里，它只属于 freedesktop 菜单。&lt;/p&gt;

&lt;p&gt;现在可以直接在系统菜单找到 emacsclient 菜单, 而且右键可以正常使用 &lt;em&gt;Open With &quot;emacsclient&quot;&lt;/em&gt;。由于 Emacs 的启动速度问题解决了，mousepad 就基本推出历史舞台了.&lt;/p&gt;

&lt;h1 id=&quot;windows-10-安装&quot;&gt;Windows 10 安装&lt;/h1&gt;

&lt;p&gt;Refer to &lt;a href=&quot;http://www.jianshu.com/p/b4cf683c25f3&quot;&gt;从零开始——Emacs 安装配置使用教程 2015&lt;/a&gt;, &lt;a href=&quot;https://www.emacswiki.org/emacs/EmacsMsWindowsIntegration&quot;&gt;Windows Integration&lt;/a&gt; and &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Microsoft-Windows.html&quot;&gt;Emacs Windows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Windows 可在 Powershell 下或取系统的环境变量：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get-item env:&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;只需解圧即可，放到 &lt;em&gt;c:\emacs* 下。首先把 *c:\emacs\bin&quot; 加进 PATH, 这样可在 CMD 或 PowerShell 下运行。凡涉及到运行，选 *runemacs.exe&lt;/em&gt; 而非 &lt;em&gt;emacs.exe&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;设置当前用户的 HOME 环境变量为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%APPDATA%&lt;/code&gt;, 即为 &lt;em&gt;c:\users\username\appdata\roaming&lt;/em&gt;. 在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HOME\.emacs.d\&lt;/code&gt; 下建 &lt;em&gt;init.el&lt;/em&gt; 配制文件。&lt;/p&gt;

    &lt;p&gt;注意这里是给当前用户设置，而不是给系统设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;设置快捷键。在桌面新建快捷键，设置为 &lt;em&gt;c:\emacs\bin\emacsclientw.exe -n -c –alternate-editor=&quot;&quot;&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;同时，修改属性里的 Start In 为 &lt;em&gt;%USERPROFILE%\Documents&lt;/em&gt;, 这样 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c-x c-f&lt;/code&gt; 时默认目录是 Start In. 同时，把快捷键放一份到 &lt;em&gt;C:\ProgramData\Microsoft\Windows\Start Menu&lt;/em&gt; 下。&lt;/p&gt;

    &lt;p&gt;还有一个办法是，在 &lt;em&gt;init.el&lt;/em&gt; 里加一句&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;default-directory&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C:/Users/Username/Documents&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;这个办法的缺点是，没法灵活设置不同的默认目录。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://blogs.technet.microsoft.com/windowsinternals/2017/10/25/windows-10-how-to-configure-file-associations-for-it-pros/&quot;&gt;文件关联&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;千万不要用参考文献里的 &lt;em&gt;ftype&lt;/em&gt; 和 &lt;em&gt;assoc&lt;/em&gt;, 不仅没有效果，还会搞乱注册表。最简单的方法是用 Windows 10, Settings, Apps, Default apps.&lt;/p&gt;

    &lt;p&gt;右键 Open With 需要第一次打开快捷键的位置，下次才会出现。不要运行那个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addpm.exe&lt;/code&gt;, 完全是一废物。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://superuser.com/questions/949385/map-capslock-to-control-in-windows-10&quot;&gt;Caps to Ctrl&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Squat</title>
   <link href="/2014/09/10/fitness-squat/"/>
   <updated>2014-09-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/09/10/fitness-squat</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This is to teach you how to squat. Watch it carefully before any attempt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Front Squat&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;//www.youtube.com/embed/eqdXqX-ShYI&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;//www.youtube.com/embed/52Q--5toj6o&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Back Squat&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;//www.youtube.com/embed/nEQQle9-0NA&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

</content>
 </entry>
 
 <entry>
   <title>Git Line Ending Conversion</title>
   <link href="/2014/09/08/git-line-ending-conversion/"/>
   <updated>2014-09-08T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/09/08/git-line-ending-conversion</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;End of Line style(EOL) differs on various system, especially between Windows and Unix. Team work across systems must pay due attention to EOL conversion. If not properly addressed, some commands like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt; cannot work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When adding new file or modified file to staging area, you might get errors:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fatal: LF would be replaced by CRLF in newfile.txt&lt;/code&gt;&lt;br /&gt;
or&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fatal: CRLF would be replaced by LF in newfile.txt&lt;/code&gt;&lt;/p&gt;

&lt;h1 id=&quot;in-and-out-of-the-object-database&quot;&gt;In and out of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object database&lt;/code&gt;&lt;/h1&gt;

&lt;p&gt;What is the object database? Two different operations: writing to the object database and writing out to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;working directory&lt;/code&gt;. It helps to understand these concepts a bit before moving on.&lt;/p&gt;

&lt;p&gt;You may already know that &lt;em&gt;Git has it&apos;s own database&lt;/em&gt; in that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; folder. All you need to know is that when you do something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit&lt;/code&gt; you are &lt;em&gt;writing objects into the database&lt;/em&gt;. This involves taking the files that you are committing, calculating their shas and writing them into the object database as blobs. This is what I mean when I say writing to the object database and this is when Git has a chance to run filters and do things like converting line endings.&lt;/p&gt;

&lt;p&gt;The other place that Git has a chance to run filters is when it &lt;em&gt;reads out of the object database and writes files into your working directory&lt;/em&gt;. This is what I mean when I say writing out into the working directory. Many commands in Git do this, but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout&lt;/code&gt; is the most obvious and easy to understand. This also happens when you do a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone&lt;/code&gt; or run a command like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset&lt;/code&gt; that changes your working directory.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Up here, we have two writing destinations: to the repository database and to the working directory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;parameters-that-influence&quot;&gt;Parameters that Influence&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;global config&lt;/li&gt;
  &lt;li&gt;core.autocrlf&lt;/li&gt;
  &lt;li&gt;core.eol&lt;/li&gt;
  &lt;li&gt;core.safecrlf&lt;/li&gt;
  &lt;li&gt;.gitattributes file&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text&lt;/code&gt; attribute&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eol&lt;/code&gt; attribute&lt;/li&gt;
  &lt;li&gt;System file Editor configuration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The file editor configuration should be adjusted according to the first two items. Therefore, we first discuss the previous two parameters. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global config&lt;/code&gt; applies to all the files which are detected as &lt;em&gt;text&lt;/em&gt; files, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; attributes apply to line ending conversion for specific file types resulting in fine-grained conversion control. &lt;strong&gt;One or more  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; files might exist in different directories of the repository&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global config&lt;/code&gt; is mainly set by command like&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;git config –global xxx yyy&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xxx&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yyy&lt;/code&gt; are attributes and values respectively.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; file is mainly organized as pattern lines. Each line is as:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;pattern    attr1 attr2 …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pattern&lt;/code&gt; mainly determines the file types, i.e. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.md&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.txt&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.cpp&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;global-config&quot;&gt;global config&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global config&lt;/code&gt; is set by command or mannaully edited. The command is as follows:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global core.autocrlf true/false/input
git config --global core.eol native/eol/crlf
git config --global core.safecrlf true/false/warn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global core.xxx&lt;/code&gt; to show the corresponding value. If you have not yet defined the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xxx&lt;/code&gt; value, Git have default values:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;core.autocrlf=false # don&apos;t do CRLF to LF conversion when writing to repository database
core.eol=native     # do LF to system native EOL style when writing to working tree
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Though &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol=native&lt;/code&gt; is the default setting by Git, but if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.autocrlf&lt;/code&gt; are not set, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol=native&lt;/code&gt; does nothing. It is a relatively passive parameter that come into effect only when the file line ending is normlized when writing to repository.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global config&lt;/code&gt; is for corse-grained control on line ending control, especially when no specific patterns for a file type can be found in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; file. The exact definition of the parameter is detailed in references.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.safecrlf&lt;/code&gt; is very useful, and set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; on whatever OS platform. It detects CRLF to LF conversion error when adding file to staging area. Especially when Git faultly detect a binary file to be text file. Git will give &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fatal&lt;/code&gt; error. Then you can add a pattern line in .gitattributes file for that binary file.&lt;/p&gt;

&lt;h1 id=&quot;gitattributes-file&quot;&gt;.gitattributes file&lt;/h1&gt;

&lt;p&gt;This file is the main reference for line ending conversion since Git 1.7.2 and above. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global config&lt;/code&gt; acts as the &lt;em&gt;fall-back reference&lt;/em&gt; if no pattern is defined in  .gitattributes file for specific file type (officially called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pathnames&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;A pattern line example is like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;*.jpg binary
*.png -text # same as above
*.txt text
*.md eol=lf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; file is committed into the repository and overrides an individual&apos;s core.autocrlf setting, ensuring consistent behavior for all users, regardless of their Git settings. The advantage of a .gitattributes file is that your line configurations are associated with your repository. You don&apos;t need to worry about whether or not collaborators have the same line ending settings that you do.&lt;/p&gt;

&lt;p&gt;Sometimes you would need to override an setting of an attribute for a path to &lt;strong&gt;Unspecified state&lt;/strong&gt;. This can be done by listing the name of the attribute prefixed with an exclamation point &lt;strong&gt;!&lt;/strong&gt; like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!text&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;parameter-priority&quot;&gt;Parameter Priority&lt;/h1&gt;

&lt;p&gt;If more than one pattern matches the path, a later line overrides an earlier line. When deciding what attributes are assigned to a path, Git consults &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$GIT_DIR/info/attributes&lt;/code&gt; file (which has the highest precedence), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; file in the same directory as the path in question, and its parent directories up to the toplevel of the work tree (the further the directory that contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; is from the path in question, the lower its precedence). &lt;strong&gt;Finally global and system-wide files are considered&lt;/strong&gt; (they have the lowest precedence).&lt;/p&gt;

&lt;p&gt;When the .gitattributes file is missing from the work tree, the path in the index is used as a fall-back. During checkout process, .gitattributes in the index is used and then the file in the working tree is used as a fall-back.&lt;/p&gt;

&lt;p&gt;If you wish to affect only a single repository (i.e., to assign attributes to files that are particular to one user’s workflow for that repository), then attributes should be placed in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$GIT_DIR/info/attributes&lt;/code&gt; file. Attributes which should be version-controlled and distributed to other repositories (i.e., attributes of interest to all users) should go into .gitattributes files. Attributes that should affect all repositories for a single user should be placed in a file specified by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.attributesfile&lt;/code&gt; configuration option (see git-config[1]). Its default value is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$XDG_CONFIG_HOME/git/attributes&lt;/code&gt;. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$XDG_CONFIG_HOME&lt;/code&gt; is either not set or empty, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/.config/git/attributes&lt;/code&gt; is used instead. Attributes for all users on a system should be placed in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(prefix)/etc/gitattributes&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;If several patterns for a &lt;em&gt;file type&lt;/em&gt; are found, a subsequent pattern line overrides a precedent pattern line. The last pattern line is used.&lt;/p&gt;

&lt;p&gt;Parameters in .gitattributes overrides those in global config. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.txt -text&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.autocrlf=true&lt;/code&gt; are both set, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.txt&lt;/code&gt; file will not be considered for EOL conversion.&lt;/p&gt;

&lt;h1 id=&quot;parameter-direction&quot;&gt;Parameter Direction&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.autocrlf&lt;/code&gt; determines whether whether converting CRLF to LF when writing to repository database. If yes, this implicates line ending conversion &lt;strong&gt;must&lt;/strong&gt; be carried out when writing to working tree for that file type. Normalized line ending (to repository database) files must also do line ending conversion when writing to working tree. How to do line ending when writing back?&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eol&lt;/code&gt; in .gitattributes, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol&lt;/code&gt; determines line ending conversion when writing to working tree. If no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eol&lt;/code&gt; pattern is set for a file type in .gitattributes, then use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol&lt;/code&gt; in global config. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol&lt;/code&gt; is not set in global config, then use the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol=native&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As mentioned in section &lt;em&gt;global config&lt;/em&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol&lt;/code&gt; paly its full paly only when needed. It cannot work independently without other parameters&apos; implication. If a repository bears no .gitattributes file or relevant global setting, the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol=native&lt;/code&gt; do nothing.&lt;/p&gt;

&lt;p&gt;In .gitattributes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eol&lt;/code&gt; will automatically set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text&lt;/code&gt; attributes. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.txt eol=lf&lt;/code&gt;. This means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.txt&lt;/code&gt; file line ending will be converted to LF when writing to working tree. Meanwhile, it assigns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.txt&lt;/code&gt; file as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.txt text&lt;/code&gt;. Therefore, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.txt&lt;/code&gt; will definitedly do CRLF to LF conversion when writing to repository database.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eol&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol&lt;/code&gt; only play their roles when the file is set for normalization when writing to repository database.&lt;/p&gt;

&lt;h1 id=&quot;parameter-scheme&quot;&gt;Parameter Scheme&lt;/h1&gt;

&lt;p&gt;The Git decision procedure:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;writing to repository, whether or not doing CRLF to LF conversion for a file type
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;If yes&lt;/strong&gt;, then depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eol&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol&lt;/code&gt; value to which the new line ending will be converted when writing to working tree&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;If not&lt;/strong&gt;, no line ending conversion when writing to working tree&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When editing files in different operating system, use the system native line ending scheme. This is usually set automatically by your file editor.&lt;/p&gt;

&lt;p&gt;Everything new created by editor in system working tree adopts native EOL style.&lt;/p&gt;

&lt;p&gt;By setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol=native&lt;/code&gt;. If line ending conversion is a must, then converted to native line ending style.&lt;/p&gt;

&lt;p&gt;If edited or new files are prepared for staging or committing, Git refers to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.safecrlf&lt;/code&gt; for EOL safety check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The following settings guarantee line ending in repository is LF independent of operating system, while that in working tree is operating system native value&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;windows&quot;&gt;Windows&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global core.autocrlf true
git config --global core.safecrlf true
git config --global core.eol native
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;linux&quot;&gt;Linux&lt;/h2&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config --global core.autocrlf input
git config --global core.safecrlf true
git config --global core.eol native
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.autocrlf=input&lt;/code&gt;, if a file type is determined by this setting to do CRLF to LF conversion when writing to repository databse, then this file type won&apos;t do EOL conversion when writing to working tree. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt; value to to guarantee overlooked file type by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; to do CRLF to LF conversion when writing to repository database.&lt;/p&gt;

&lt;h2 id=&quot;repository&quot;&gt;Repository&lt;/h2&gt;

&lt;p&gt;.gitattributes file contents, a example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Auto detect text files and perform LF normalization when checkin. This should be the first line for other lines below to override it.
* text=auto

# For .md file specially
 #*.md text eol=lf #eol will overwrite text, so there is no need of text attribute here
 #*.md eol=lf # eol depends on core.eol=native
*.md text

.gitattributes text

# Remove text attribute for binary files，-text and binary are the same purpose
*.jpg -text
*.jpeg binary
*.svg -text
*.png binary
*.pdf -text
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt;, there is a pattern line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;* text=auto&lt;/code&gt;, this will override the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.autocrlf=true&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.autocrlf=input&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global config&lt;/code&gt;. But we still need those two global config. Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;* text=auto&lt;/code&gt; is only for the current repository. The other repositories might not have this pattern line in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;conversion-process&quot;&gt;Conversion Process&lt;/h2&gt;

&lt;p&gt;According to the decision precedence, .gitattributes file is consulted before global config for line ending conversion.&lt;/p&gt;

&lt;p&gt;When a &lt;em&gt;file type&lt;/em&gt; is written to working tree or repository database, Git run line ending filter for that &lt;em&gt;file type&lt;/em&gt; to determine whether conversion is needed.&lt;/p&gt;

&lt;p&gt;If several entries are found for the &lt;em&gt;file type&lt;/em&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;global config&lt;/code&gt;, choose one pattern according to patameter priority.&lt;/p&gt;

&lt;p&gt;For writing to repository database, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.safecrlf&lt;/code&gt; will check EOL conversion safety before the writing happens.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;* text=auto&lt;/code&gt;: &lt;strong&gt;auto&lt;/strong&gt; firstly detects if the the file is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;binary&lt;/code&gt;.
    &lt;ul&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text&lt;/code&gt; file, then convert CRLF to LF when writing to repository database.&lt;/li&gt;
    &lt;/ul&gt;
    &lt;ul&gt;
      &lt;li&gt;Before adding file to staging area, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.safecrlf&lt;/code&gt; has already checked the conversion safety.&lt;/li&gt;
      &lt;li&gt;When writing back to working tree, according to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol=native&lt;/code&gt;, LF to CRLF conversion will be carried out on Windows. While on Linux, LF to LF will carried out.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text=auto&lt;/code&gt; is a universal setting in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitattributes&lt;/code&gt; for those file types that don&apos;t have specific pattern line in .gitattributes.
     * If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;binary&lt;/code&gt; file, then do nothing related to line ending issue.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.md&lt;/code&gt; file has specific pattern line that oeverides the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;* text=auto&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.md&lt;/code&gt; file will convert CRLF to LF when writing to repository. When writing to working tree, depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.eol=native&lt;/code&gt; in global config.&lt;/li&gt;
  &lt;li&gt;Similarly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.jpg -text&lt;/code&gt; means &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*.jpg&lt;/code&gt; file is not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text&lt;/code&gt; file but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;binary&lt;/code&gt; file. So no line ending conversion is associated with it. This also applies to other picture formats and PDF file.&lt;/li&gt;
  &lt;li&gt;When you modify a file or add a new file type, then adding to staging area, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.safecrlf&lt;/code&gt; will do safety verification. If error occurs, then you can:
    &lt;ul&gt;
      &lt;li&gt;adjust your the file line ending style to allow staging.&lt;/li&gt;
      &lt;li&gt;add a specific line in .gitattributes for fine-grained control on line ending conversion for that file.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;refreshing-a-repository-after-changing-line-endings&quot;&gt;Refreshing a repository after changing line endings&lt;/h1&gt;

&lt;p&gt;According to the previous setting scheme, EOL in repository databse both in Windows and Linux should be LF. If the database or working tree contains CRLF previously, you may found git wants to commit files that you have not modified.&lt;/p&gt;

&lt;p&gt;The best way to automatically configure your repository&apos;s line endings is to first backup your files with Git, delete every file in your repository (except the .git directory), and then restore the files all at once.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git add . -u
git commit -m &quot;Saving files before refreshing line endings&quot;
git rm --cached -r .
git reset --hard
git add .
# It is perfectly safe to see a lot of messages here that read
# &quot;warning: CRLF will be replaced by LF in file.&quot; or &quot;fatal: CRLF will be replaced by LF in file.&quot;
# How to solve the fatal error read the first reference.
git commit -m &quot;Normalize all the line endings&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;read-the-1st-and-2nd-reference-carefully&quot;&gt;Read the 1st and 2nd reference carefully!&lt;/h1&gt;

&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/26991025/fatal-lf-would-be-replaced-by-crlf&quot;&gt;fatal: LF would be replaced by CRLF&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/&quot;&gt;Mind the End of Your Line&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.github.com/articles/dealing-with-line-endings/#platform-all&quot;&gt;dealing-with-line-endings&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ninehills/blog.ninehills.info/blob/master/2012-5-line-endings-in-git.md&quot;&gt;line-endings-in-git&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.csdn.net/leonzhouwei/article/details/8933605#t0&quot;&gt;GitHub 第一坑换行符自动转换&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://git-scm.com/docs/gitattributes&quot;&gt;gitattributes - defining attributes per path&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.subgit.com/line-endings-handling-in-svn-git-and-subgit/&quot;&gt;Line endings handling in SVN, Git and SubGit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;[fatal: LF would be replaced by CRLF in &lt;some file=&quot;&quot; in=&quot;&quot; the=&quot;&quot; repo=&quot;&quot;&gt;](http://stackoverflow.com/questions/15467507/trying-to-commit-git-files-but-getting-fatal-lf-would-be-replaced-by-crlf-in)&lt;/some&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://git-scm.com/docs/git-config&quot;&gt;core.eol core.autocrlf&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>App server VS. Web server</title>
   <link href="/2014/08/11/appserver-webserver/"/>
   <updated>2014-08-11T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/08/11/appserver-webserver</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Describe the difference between application server and web server. Pay due attention to their correlation as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most of the times these terms Web Server and Application server are used interchangeably.&lt;/p&gt;

&lt;p&gt;Following are some of the key differences in features of Web Server and Application Server:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Web Server is designed to serve HTTP Content. App Server can also serve HTTP Content but is not limited to just HTTP. It can be provided other protocol support such as RMI/RPC&lt;/li&gt;
  &lt;li&gt;Web Server is mostly designed to serve static content, though most Web Servers have plugins to support scripting languages like Perl, PHP, ASP, JSP etc. through which these servers can generate dynamic HTTP content.&lt;/li&gt;
  &lt;li&gt;Most of the application servers have Web Server as integral part of them, that means App Server can do whatever Web Server is capable of. Additionally App Server have components and features to support Application level services such as Connection Pooling, Object Pooling, Transaction Support, Messaging services etc.&lt;/li&gt;
  &lt;li&gt;As web servers are well suited for static content and app servers for dynamic content, most of the production environments have web server acting as reverse proxy to app server. That means while servicing a page request, static contents (such as images/Static HTML) are served by web server that interprets the request. Using some kind of filtering technique (mostly extension of requested resource) web server identifies dynamic content request and transparently forwards to app server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example of such configuration is Apache Tomcat HTTP Server and Oracle (formerly BEA) WebLogic Server. Apache Tomcat HTTP Server is Web Server and Oracle WebLogic is Application Server.&lt;/p&gt;

&lt;p&gt;In some cases the servers are tightly integrated such as IIS and .NET Runtime. IIS is web server. When equipped with .NET runtime environment, IIS is capable of providing application services.&lt;/p&gt;

&lt;p&gt;Both terms are very generic, one containing the other one and vice versa in some cases.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Web server: serves content to the web using http protocol.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Application server: hosts and exposes business logic and processes.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think that the main point is that the web server exposes everything through the http protocol, while the application server is not restricted to it.&lt;/p&gt;

&lt;p&gt;That said, in many scenarios you will find that the web server is being used to create the front-end of the application server, that is, it exposes a set of web pages that allow the user to interact with the business rules found into the application server.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>VBS Programing Tutorial</title>
   <link href="/2014/07/12/vbs-programming/"/>
   <updated>2014-07-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/07/12/vbs-programming</id>
   <content type="html">&lt;div class=&quot;message&quot;&gt;
一个很详尽的VBS介绍。
&lt;/div&gt;

&lt;p&gt;Vbs脚本编程简明教程之一—为什么要使用Vbs？&lt;/p&gt;

&lt;p&gt;在Windows中，学习计算机操作也许很简单，但是很多计算机工作是重复性劳动，例如你每周也许需要对一些计算机文件进行复制、粘贴、改名、删除，也许你每天启动计算机第一件事情就是打开WORD，切换到你喜爱的输入法进行文本编辑，同时还要播放优美的音乐给工作创造一个舒心的环境，当然也有可能你经常需要对文本中的某些数据进行整理，把各式各样的数据按照某种规则排列起来……。这些事情重复、琐碎，使人容易疲劳。&lt;/p&gt;

&lt;p&gt;第三方软件也许可以强化计算机的某些功能，但是解决这些重复劳动往往事倍功半，我也尝试过使用计算机语言编写程序来解决这些问题，但是随之而来的命令、语法、算法、系统框架和类库常常让我觉得这样是否有必要，难道就是因为猪毛比较难拔，所以我就要去学习机械，为自己设计一个拔猪毛机(?)吗？&lt;/p&gt;

&lt;p&gt;Vbs是一种Windows脚本，它的全称是:Microsoft Visual Basic Script Editon.(微软公司可视化BASIC脚本版)，VBS是Visual Basic的的一个抽象子集，是系统内置的，用它编写的脚本代码不能编译成二进制文件，直接由Windows系统执行（实际是一个叫做宿主host的解释源代码并执行），高效、易学，但是大部分高级语言能干的事情，它基本上都具备，它可以使各种各样的任务自动化，可以使你从重复琐碎的工作中解脱出来，极大的提高工作效率。&lt;/p&gt;

&lt;p&gt;我个人认为Vbs脚本其实就是一种计算机编程语言，但是由于缺少计算机程序设计语言中的部分要素，对于事件的描述能力较弱，所以称为脚本，它最方便的地方就是提供了对COM对象的简便支持。那么什么是COM对象呢？&lt;/p&gt;

&lt;p&gt;我这样理解，COM对象就是一些具有特定函数功能项程序模块，他们一般以ocx或者dll作为扩展名，你只要找到包含有你需要的功能的模块文件，并在脚本中规范的引用，就可以实现特定的功能，也就是说Vbs脚本就是调用现成的“控件”作为对象，用对象的属性和方法实现目的，完全免去了编写代码、设计算法等等麻烦。说白了，我不是觉得拔猪毛麻烦么？我发觉xx机（比如真空离心器）有一个功能可以实现脱毛，ok，我把它拿来给猪脱毛。什么？大材小用？太浪费资源了？天哪，那是计算机芯片的事情，死道友不死贫道，反正我的事情是方便快速的解决了，这就行了。&lt;/p&gt;

&lt;p&gt;最方便的是它甚至不需要专门的开发环境，在你的计算机中，只要有notepad，就可以编写Vbs脚本了，并且可以直接执行。&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之二—如何开始第一个Vbs脚本？&lt;/p&gt;

&lt;p&gt;就像多数计算机教程一样，我们从“Hello World！”程序开始我们的练习。什么？不知道是什么意思？就是说大部分的计算机程序设计教程开篇入门都是编写一个小程序，执行这个程序的结果就是在计算机的屏幕上或者dos窗口中显示一行文字：Hello World！好了，我们开始吧。&lt;/p&gt;

&lt;p&gt;打开你的“记事本”程序，在编辑窗口填写：&lt;/p&gt;

&lt;p&gt;msgbox &quot;Hello World!&quot;&lt;/p&gt;

&lt;p&gt;然后用鼠标单击“文件”菜单，单击“保存”，把“保存在”一栏设为桌面，在“文件名”一栏中填写kk.vbs，单击“保存”就可以了。然后最小化“记事本”窗口，在桌面上寻找你刚刚保存的kk.vbs，然后双击。看到弹出的对话框了没有，单击“确定”，对话框消失了。难看了点，不过确实是你编写的第一个脚本程序。&lt;/p&gt;

&lt;p&gt;说明之一：上面的操作中，保存位置放在桌面，仅仅是为了执行方便，你保存到其他的地方完全没有问题，只要你知道你保存在什么地方就可以了，什么？是废话，自己保存的当然知道保存在那里了。不，自己保存的文件自己找不到的人我见的多了去了。文件名你可以随意填写，不一定非要写kk，只要符合Windows的文件命名规则就可以了，但是扩展名必须是vbs，什么?不知道什么是扩展名？就是文件名中“.”后的那部分，简单说，就是vbs脚本文件命名时必须是：xxx.vbs，其中xxx你随意。&lt;/p&gt;

&lt;p&gt;说明之二：在记事本编辑窗口中写的这行是什么意思？&lt;/p&gt;

&lt;p&gt;Msgbox是VBS内建的函数，每一个函数都可以完成一定的功能，你只需要按照语法要求，在函数的相应部分填写相应的内容就可以了，这部分内容我们称为参数，当然函数执行的结果我们称为返回值，一个函数可以有返回值也可以没有，可以有参数也可以没有。你不用了解函数是怎么运作的，只要了解这个函数能干什么就行了。&lt;/p&gt;

&lt;p&gt;Msgbox语法：msgbox &quot;对话框内容&quot;, , &quot;对话框的标题&quot;&lt;/p&gt;

&lt;p&gt;你不妨用记事本打开刚才的文件在编辑窗口中输入：&lt;/p&gt;

&lt;p&gt;msgbox &quot;Hello World!&quot; , , &quot;系统提示&quot;&lt;/p&gt;

&lt;p&gt;执行一下，看看效果和位置。&lt;/p&gt;

&lt;p&gt;说明之三：如果执行失败，看看你的标点符号，所有的标点符号必须是在英文状态下输入的。&lt;/p&gt;

&lt;p&gt;当然，这个脚本实在是太简单了，甚至连最简单的交互都没有，所以你可以把脚本这样修改一下：&lt;/p&gt;

&lt;p&gt;Dim name&lt;/p&gt;

&lt;p&gt;name=Inputbox(&quot;请输入你的名字:&quot;,&quot;名称&quot;)&lt;/p&gt;

&lt;p&gt;Msgbox name, , &quot;您的名字是&quot;&lt;/p&gt;

&lt;p&gt;保存执行一下，看到弹出的对话框了么？填入你的名字，点确定，看到结果了吗？&lt;/p&gt;

&lt;p&gt;说明之一：第一句是定义变量，dim是定义变量的语句&lt;/p&gt;

&lt;p&gt;其格式为：dim 变量1,变量2……，&lt;/p&gt;

&lt;p&gt;Vbs只有一种变量类型，所以不用声明变量类型。系统会自动分辨变量类型。&lt;/p&gt;

&lt;p&gt;说明之二：inputbox是VBS内建的函数，可以接受输入的内容，其语法格式为：&lt;/p&gt;

&lt;p&gt;Inputbox(&quot;对话框内容&quot;,&quot;对话框标题&quot;)&lt;/p&gt;

&lt;p&gt;第二句的意思是接受用户的输入，并把输入结果传递给变量name。&lt;/p&gt;

&lt;p&gt;好了，到此脚本基本的输入输出函数都有了，已经可以完成一些比较简单的功能了，你可以编写一个简单的脚本，然后拷贝的“程序”—&amp;gt;“启动”中，然后重新启动计算机看看结果。&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之三—Vbs的基本语法（牢记）&lt;/p&gt;

&lt;p&gt;VBScript基础知识&lt;/p&gt;

&lt;p&gt;一、变量&lt;/p&gt;

&lt;p&gt;1、所有单引号后面的内容都被解释为注释。&lt;/p&gt;

&lt;p&gt;2、在VBScript中，变量的命名规则遵循标准的命名规则，需要注意的是：在VBScript中对变量、方法、函数和对象的引用是不区分大小写的。在申明变量时，要显式地申明一个变量，需要使用关键字DIm来告诉VBScript你要创建一个变量，并将变量名称跟在其后。申明多个同类型变量，可以用逗号分隔。注意：VBScript中不允许在申明变量的时候同时给变量赋值。但是允许在一行代码内同时对两个变量进行赋值，中间用冒号分隔。&lt;/p&gt;

&lt;p&gt;3、你可以使用OptionExplicit来告诉宿主变量必须先声明后使用。&lt;/p&gt;

&lt;p&gt;4、VBScript在定义时只有一种变量类型，在实际使用中需要使用类型转换函数来将变量转换成相应的变量类型。&lt;/p&gt;

&lt;p&gt;Cbool函数将变量转换成布尔值；&lt;/p&gt;

&lt;p&gt;Cbyte函数将变量转换为0到255之间的整数。&lt;/p&gt;

&lt;p&gt;Ccur函数、Cdbl函数和Csng函数将变量转换为浮点数值，前者只精确到小数点后四位，后两者要更加精确，数值的范围也要大的多。&lt;/p&gt;

&lt;p&gt;Cdate函数将变量转换为日期值。&lt;/p&gt;

&lt;p&gt;Cint函数和Clng函数将变量转换为整数，后者的范围比前者要大的多。&lt;/p&gt;

&lt;p&gt;Cstr函数将变量转换为字符串。&lt;/p&gt;

&lt;p&gt;二、数组&lt;/p&gt;

&lt;p&gt;数组的定义与变量非常类似，只需要在变量后描述这个数组的个数和维数。需要注意的是：数组的下标总是从0开始，而以数组定义中数值减一结束。也就是说你以要定义一个有十个数据的数组，将这样书写代码：dImarray（9），同样，当你要访问第五个元素时，实际的代码是array(4)。当然，你可以通过不指定数组的个数和维数来申明动态数组。等到数组的个数和维数固定后，使用关键字redim来改变数组。注意，在改变数组的大小时，数组的数据会被破坏，使用关键字preserve来保护数据。例如：&lt;/p&gt;

&lt;p&gt;RedIm空格preserve空格array括号个数逗号维数括号&lt;/p&gt;

&lt;p&gt;三、操作符&lt;/p&gt;

&lt;p&gt;在VBScript运算符中，加减乘除都是我们常用的符号，乘方使用的是 ^ ，取模使用的Mod。&lt;/p&gt;

&lt;p&gt;在比较操作符中，等于、小于、大于、小于等于、大于等于都与我们常用的符号是一致的，而不等于是小于和大于连用。&lt;/p&gt;

&lt;p&gt;逻辑运算符为：和操作—&amp;gt;AND     非操作—&amp;gt;NOT     或操作—&amp;gt;OR；&lt;/p&gt;

&lt;p&gt;你可以使用操作符 + 和操作符 &amp;amp; 来连接字符串，一般使用&amp;amp;操作符；&lt;/p&gt;

&lt;p&gt;另外还有一个比较特殊的操作符Is用来比较对象，例如按钮对象，如果对象是同一类型，结果就是真，如果对象不是同一类型，结果就是假。&lt;/p&gt;

&lt;p&gt;四、条件语句主要有if……then语句和selectcase语句两种形式&lt;/p&gt;

&lt;p&gt;在if……then语句中，其基本形式为：&lt;/p&gt;

&lt;p&gt;If 条件 then&lt;/p&gt;

&lt;p&gt;处理条件的语句；&lt;/p&gt;

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

&lt;p&gt;Endif&lt;/p&gt;

&lt;p&gt;基本形式只能对单个条件进行验证，如果有两个条件，则需要在基本形式中添加单行语句else，如果还有更多的条件需要验证，则需要添加语句&lt;/p&gt;

&lt;p&gt;Elseif 条件 then&lt;/p&gt;

&lt;p&gt;处理条件语句&lt;/p&gt;

&lt;p&gt;在selectcase语句中，其基本形式为：&lt;/p&gt;

&lt;p&gt;Select case 变量&lt;/p&gt;

&lt;p&gt;Case 条件值&lt;/p&gt;

&lt;p&gt;处理条件语句&lt;/p&gt;

&lt;p&gt;并对上两句进行重复&lt;/p&gt;

&lt;p&gt;最后一句应为&lt;/p&gt;

&lt;p&gt;case else&lt;/p&gt;

&lt;p&gt;处理语句&lt;/p&gt;

&lt;p&gt;当然不要忘记将条件结束语句End select放在最后一行&lt;/p&gt;

&lt;p&gt;注意：在执行字符串比较时，需要特别注意大小写，一般情况下，我们在比较前，使用lcase函数将字符串转换成小写，使用ucase函数将字符串转换成大写大写。&lt;/p&gt;

&lt;p&gt;五、循环控制语句&lt;/p&gt;

&lt;p&gt;循环控制语句有for……next循环、for……each循环、do……while循环、do……until循环、while循环五种形式。&lt;/p&gt;

&lt;p&gt;在使用循环控制语句前，首先要对循环条件进行判断，如果循环次数是有固定次数的，那么使用For……next循环，其结构为：&lt;/p&gt;

&lt;p&gt;For   计数器变量＝开始计数值 to 最后计数值&lt;/p&gt;

&lt;p&gt;执行循环体&lt;/p&gt;

&lt;p&gt;Next&lt;/p&gt;

&lt;p&gt;如果是需要对数组或对象集合中的每一个元素进行判断，则需要使用for……each循环，其结构为：&lt;/p&gt;

&lt;p&gt;For each 循环计数变量 in 要查看的对象或数组&lt;/p&gt;

&lt;p&gt;执行处理语句&lt;/p&gt;

&lt;p&gt;Next&lt;/p&gt;

&lt;p&gt;注意：在上述两种循环中随时可以使用exit for来退出循环&lt;/p&gt;

&lt;p&gt;如果你希望在条件满足时执行一段代码则使用do……while语句，结构为：&lt;/p&gt;

&lt;p&gt;Do while 条件&lt;/p&gt;

&lt;p&gt;执行循环体&lt;/p&gt;

&lt;p&gt;Loop&lt;/p&gt;

&lt;p&gt;如果你希望在条件不满足时执行代码，则使用do……until语句，结构为：&lt;/p&gt;

&lt;p&gt;Do　until　条件&lt;/p&gt;

&lt;p&gt;执行循环体&lt;/p&gt;

&lt;p&gt;Loop&lt;/p&gt;

&lt;p&gt;当然，在这两种循环语句中，你可以使用exit do来退出循环&lt;/p&gt;

&lt;p&gt;最后一种循环语句是条件满足时一直执行循环，&lt;/p&gt;

&lt;p&gt;While 条件&lt;/p&gt;

&lt;p&gt;执行循环体&lt;/p&gt;

&lt;p&gt;Wend&lt;/p&gt;

&lt;p&gt;六、使用过程&lt;/p&gt;

&lt;p&gt;常用的过程有两种，一种为函数，给调用者返回值，一种为子程序，无返回值，还有一种叫事件的特殊子程序，用的比较少。&lt;/p&gt;

&lt;p&gt;函数的基本定义方法为：&lt;/p&gt;

&lt;p&gt;Function 函数名称（参数列表）&lt;/p&gt;

&lt;p&gt;函数代码&lt;/p&gt;

&lt;p&gt;函数名称＝某值‘用来返回值&lt;/p&gt;

&lt;p&gt;end function&lt;/p&gt;

&lt;p&gt;子程序一些都类似，不过没有返回值&lt;/p&gt;

&lt;p&gt;注意：尽管在定义子程序的时候，参数列表要加括号，但在调用子程序的时候，参数列表不加括号，括号只在函数中使用。另外，子程序不能在表达式中使用。&lt;/p&gt;

&lt;p&gt;而函数只能出现在赋值语句的右边，或者表达式中，函数不能直接使用，如果必须直接使用函数，则必须使用call语句调用，并取消返回值。&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之四—如何利用Vbs运行外部程序？&lt;/p&gt;

&lt;p&gt;Vbs只提供了编程的一个基本框架，用户可以使用Vbs来定义变量、过程和函数，vbs也提供了一些内部函数和对象，但是Vbs没有提供任何命令来访问Windows系统内部的部件，但是值得庆幸的是，Vbs虽然不能自己完成这些任务，但是它提供了一条极为方便、功能也相当强的命令——CreateObject，这条命令可以访问windows系统内安装的所有com对象，并且可以调用这些部件中存放的命令。&lt;/p&gt;

&lt;p&gt;于是问题解决了，比如说，我手头有1000个小文本，我首先要对每一个文本的语法进行查错和修改，然后按照预先定义好的规则对这些文本进行排序，最后将这些文本合并成为一个文件。正常情况下，我们需要把打开第一个小文本，然后把它复制到WORD中，然后利用里面的除错功能进行除错和修改，然后再导入到EXCEL中进行排序，将这个过程重复1000遍，然后再将所有得到的文本复制到一个大文本中。实在是太枯燥、工作量太大了。有了Vbs和CreateObject，问题得到解决，我只需要找到相应的模块，调用相应的功能就可以了，作为脚本，把一个枯燥的过程重复1000次，本就是它的拿手好戏。&lt;/p&gt;

&lt;p&gt;好了，我们走入正题，从最简单的——只启动一个程序开始。&lt;/p&gt;

&lt;p&gt;WSH也就是用来解析Vbs的宿主，本身包含了几个个常用对象：&lt;/p&gt;

&lt;p&gt;1、Scripting.FileSystemObject —&amp;gt; 提供一整套文件系统操作函数&lt;/p&gt;

&lt;p&gt;2、Scripting.Dictionary —&amp;gt; 用来返回存放键值对的字典对象&lt;/p&gt;

&lt;p&gt;3、Wscript.Shell —&amp;gt; 提供一套读取系统信息的函数，如读写注册表、查找指定文件的路径、读取DOS环境变量，读取链接中的设置&lt;/p&gt;

&lt;p&gt;4、Wscript.NetWork —&amp;gt;&lt;/p&gt;

&lt;p&gt;提供网络连接和远程打印机管理的函数。（其中，所有Scripting对象都存放在SCRRUN.DLL文件中，所有的Wscript对象都存放在WSHOM.ocx文件中。）&lt;/p&gt;

&lt;p&gt;现在我们需要的是第三个对象，好了，让我们先连接一下对象看看，在记事本的编辑窗口中输入：&lt;/p&gt;

&lt;p&gt;Set objShell = CreateObject(“Wscript.Shell”)&lt;/p&gt;

&lt;p&gt;objShell.Run “notepad”&lt;/p&gt;

&lt;p&gt;同样，保存执行。那么看到了一个什么样的结果呢？在桌面上又打开了一个记事本。&lt;/p&gt;

&lt;p&gt;说明之一：Set是Vbs指令，凡是将一对象引用赋给变量，就需要使用set关键字。那么什么是对象引用呢？凡是字符串、数值、布尔值之外的变量都是对象引用。Objshell是变量名，可以随意修改。&lt;/p&gt;

&lt;p&gt;说明之二：反是正确引用的对象，其本身内置有函数和变量，其引用方法为在变量后加“. ”，后紧跟其实现功能的函数就可以了。Objshell.run&lt;/p&gt;

&lt;p&gt;的意思就是调用Wscript.shell中的运行外部程序的函数——run，notepad是记事本程序的文件名。当然你也可以改成“calc”，这是计算器的文件名，winword是word的文件名，等等吧，所有可执行文件的文件名都可以。但是需要注意的是，如果你要执行的可执行文件存放的地方不是程序安装的常用路径，一般情况下，需要提供合法的路径名，但是run在运行解析时，遇到空格会停止，解决的方法是使用双引号，例如：在我的机器上运行qq，代码为：&lt;/p&gt;

&lt;p&gt;objshell.run &quot;&quot;&quot;C:&quot;Program Files&quot;QQ2006&quot;QQ.exe&quot;&quot;&quot; ‘注：三个引号&lt;/p&gt;

&lt;p&gt;好，我们再进一步，启动两个程序会如何呢？&lt;/p&gt;

&lt;p&gt;输入如下代码：&lt;/p&gt;

&lt;p&gt;Set objShell = CreateObject(“Wscript.Shell”)&lt;/p&gt;

&lt;p&gt;objShell.Run “notepad”&lt;/p&gt;

&lt;p&gt;objShell.Run “calc”&lt;/p&gt;

&lt;p&gt;执行会如何呢？两个程序基本上同时启动了。如果我们需要先启动notepad再启动calc将如何呢？很简单在需要顺序执行的代码后加 , , True参数就可以了。&lt;/p&gt;

&lt;p&gt;好了输入代码：&lt;/p&gt;

&lt;p&gt;Set objShell = CreateObject(“Wscript.Shell”)&lt;/p&gt;

&lt;p&gt;objShell.Run “notepad” ,,true&lt;/p&gt;

&lt;p&gt;objShell.Run “calc”&lt;/p&gt;

&lt;p&gt;看看执行的结果怎么样吧！&lt;/p&gt;

&lt;p&gt;总结：run函数有三个参数，第一个参数是你要执行的程序的路径，第二个程序是窗口的形式，0是在后台运行；1表示正常运行；2表示激活程序并且显示为最小化；3表示激活程序并且显示为最大化；一共有10个这样的参数我只列出了4个最常用的。&lt;/p&gt;

&lt;p&gt;第三个参数是表示这个脚本是等待还是继续执行，如果设为了true,脚本就会等待调用的程序退出后再向后执行。&lt;/p&gt;

&lt;p&gt;其实，run做为函数，前面还有一个接受返回值的变量，一般来说如果返回为0，表示成功执行，如果不为0，则这个返回值就是错误代码，可以通过这个代码找出相应的错误。&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之五—错误处理&lt;/p&gt;

&lt;p&gt;引发错误的原因有很多，例如用户输入了错误类型的值，或者脚本找不到必需的文件、目录或者驱动器，我们可以使用循环技术来处理错误，但是VBS本身也提供了一些基本技术来进行错误的检测和处理。&lt;/p&gt;

&lt;p&gt;1、最常见的错误是运行时错误，也就是说错误在脚本正在运行的时候发生，是脚本试图进行非法操作的结果。例如零被作为除数。在vbs中，任何运行时错误都是致命的，此时，脚本将停止运行，并在屏幕上显示一个错误消息。你可以在脚本的开头添加&lt;/p&gt;

&lt;p&gt;On Error Resume Next&lt;/p&gt;

&lt;p&gt;这行语句可以告诉vbs在运行时跳过发生错误的语句，紧接着执行跟在它后面的语句。&lt;/p&gt;

&lt;p&gt;发生错误时，该语句将会把相关的错误号、错误描述和相关源代码压入错误堆栈。&lt;/p&gt;

&lt;p&gt;2、虽然On Error Resume&lt;/p&gt;

&lt;p&gt;Next语句可以防止vbs脚本在发生错误时停止运行，但是它并不能真正处理错误，要处理错误，你需要在脚本中增加一些语句，用来检查错误条件并在错误发生时处理它。&lt;/p&gt;

&lt;p&gt;vbscript提供了一个对象err对象，他有两个方法clear，raise，5个属性：description，helpcontext，helpfile，number，source&lt;/p&gt;

&lt;p&gt;err对象不用引用实例，可以直接使用，例如：&lt;/p&gt;

&lt;p&gt;on error resume next&lt;/p&gt;

&lt;p&gt;a=11&lt;/p&gt;

&lt;p&gt;b=0&lt;/p&gt;

&lt;p&gt;c=a/b&lt;/p&gt;

&lt;p&gt;if err.number&amp;lt;&amp;gt;0 then&lt;/p&gt;

&lt;p&gt;wscript.echo err.number &amp;amp; err.description &amp;amp; err.source&lt;/p&gt;

&lt;p&gt;end if&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之六—修改注册表&lt;/p&gt;

&lt;p&gt;Vbs中修改注册表的语句主要有：&lt;/p&gt;

&lt;p&gt;1、读注册表的关键词和值：&lt;/p&gt;

&lt;p&gt;可以通过把关键词的完整路径传递给wshshell对象的regread方法。例如：&lt;/p&gt;

&lt;p&gt;set ws=wscript.createobject(&quot;wscript.shell&quot;)&lt;/p&gt;

&lt;p&gt;v=ws.regread(&quot;HKEY_LOCAL_MACHINE&quot;SOFTWARE&quot;Microsoft&quot;Windows&quot;CurrentVersion&quot;Run&quot;nwiz&quot;)&lt;/p&gt;

&lt;p&gt;wscript.echo v&lt;/p&gt;

&lt;p&gt;2、写注册表&lt;/p&gt;

&lt;p&gt;使用wshshell对象的regwrite方法。例子：&lt;/p&gt;

&lt;p&gt;path=&quot;HKEY_LOCAL_MACHINE&quot;SOFTWARE&quot;Microsoft&quot;Windows&quot;CurrentVersion&quot;Run&quot;&quot;&lt;/p&gt;

&lt;p&gt;set ws=wscript.createobject(&quot;wscript.shell&quot;)&lt;/p&gt;

&lt;p&gt;t=ws.regwrite(path &amp;amp; &quot;jj&quot;,&quot;hello&quot;)&lt;/p&gt;

&lt;p&gt;这样就把&lt;/p&gt;

&lt;p&gt;HKEY_LOCAL_MACHINE&quot;SOFTWARE&quot;Microsoft&quot;Windows&quot;CurrentVersion&quot;Run&quot;jj这个键值改成了hello.不过要注意：这个键值一定要预先存在。&lt;/p&gt;

&lt;p&gt;如果要创建一个新的关键词，同样也是用这个方法。&lt;/p&gt;

&lt;p&gt;path=&quot;HKEY_LOCAL_MACHINE&quot;SOFTWARE&quot;Microsoft&quot;Windows&quot;CurrentVersion&quot;run&quot;sssa2000&quot;love&quot;&quot;&lt;/p&gt;

&lt;p&gt;set ws=wscript.createobject(&quot;wscript.shell&quot;)&lt;/p&gt;

&lt;p&gt;val=ws.regwrite(path,&quot;nenboy&quot;)&lt;/p&gt;

&lt;p&gt;val=ws.regread(path)&lt;/p&gt;

&lt;p&gt;wscript.echo val&lt;/p&gt;

&lt;p&gt;删除关键字和值&lt;/p&gt;

&lt;p&gt;使用regdelete方法，把完整的路径传递给regdelete就可以了&lt;/p&gt;

&lt;p&gt;例如&lt;/p&gt;

&lt;p&gt;val=ws.regdel(path)&lt;/p&gt;

&lt;p&gt;注意，如果要删除关键词的值的话一定要在路径最后加上“&quot;”，如果不加斜线，就会删除整个关键词。&lt;/p&gt;

&lt;p&gt;当然，从现在的角度看，还是使用WMI的注册表处理功能也许更好些。&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之七—FSO的常见对象和方法&lt;/p&gt;

&lt;p&gt;文件系统是所有操作系统最重要的部分之一，脚本经常会需要对文件及文件夹进行访问和管理，在Vbs中对桌面和文件系统进行访问的顶级对象是FileSystemObject(FSO)，这个对象特别复杂，是vbs进行文件操作的核心。此节内容应了如指掌。&lt;/p&gt;

&lt;p&gt;FSO包含的常见对象有：&lt;/p&gt;

&lt;p&gt;Drive对象：包含储存设备的信息，包括硬盘、光驱、ram盘、网络驱动器&lt;/p&gt;

&lt;p&gt;Drives集合：提供一个物理和逻辑驱动器的列表&lt;/p&gt;

&lt;p&gt;File 对象：检查和处理文件&lt;/p&gt;

&lt;p&gt;Files 集合：提供一个文件夹中的文件列表&lt;/p&gt;

&lt;p&gt;Folder对象：检查和处理文件夹&lt;/p&gt;

&lt;p&gt;Folders集合：提供文件夹中子文件夹的列表&lt;/p&gt;

&lt;p&gt;Textstream对象：读写文本文件&lt;/p&gt;

&lt;p&gt;FSO的常见方法有：&lt;/p&gt;

&lt;p&gt;BulidPath：把文件路径信息添加到现有的文件路径上&lt;/p&gt;

&lt;p&gt;CopyFile：复制文件&lt;/p&gt;

&lt;p&gt;CopyFolder：复制文件夹&lt;/p&gt;

&lt;p&gt;CreateFolder：创建文件夹&lt;/p&gt;

&lt;p&gt;CreateTextFile：创建文本并返回一个TextStream对象&lt;/p&gt;

&lt;p&gt;DeleteFile：删除文件&lt;/p&gt;

&lt;p&gt;DeleteFolder：删除文件夹及其中所有内容&lt;/p&gt;

&lt;p&gt;DriveExits：确定驱动器是否存在&lt;/p&gt;

&lt;p&gt;FileExits：确定一个文件是否存在&lt;/p&gt;

&lt;p&gt;FolderExists：确定某文件夹是否存在&lt;/p&gt;

&lt;p&gt;GetAbsolutePathName：返回一个文件夹或文件的绝对路径&lt;/p&gt;

&lt;p&gt;GetBaseName：返回一个文件或文件夹的基本路径&lt;/p&gt;

&lt;p&gt;GetDrive：返回一个dreve对象&lt;/p&gt;

&lt;p&gt;GetDriveName：返回一个驱动器的名字&lt;/p&gt;

&lt;p&gt;GetExtensionName：返回扩展名&lt;/p&gt;

&lt;p&gt;GetFile：返回一个file对象&lt;/p&gt;

&lt;p&gt;GetFileName：返回文件夹中文件名称&lt;/p&gt;

&lt;p&gt;GetFolder：返回一个文件夹对象&lt;/p&gt;

&lt;p&gt;GetParentFolderName：返回一个文件夹的父文件夹&lt;/p&gt;

&lt;p&gt;GetSpecialFolder:返回指向一个特殊文件夹的对象指针&lt;/p&gt;

&lt;p&gt;GetTempName:返回一个可以被createtextfile使用的随机产生的文件或文件夹的名称&lt;/p&gt;

&lt;p&gt;MoveFile：移动文件&lt;/p&gt;

&lt;p&gt;MoveFolder：移动文件夹&lt;/p&gt;

&lt;p&gt;OpenTextFile：打开一个存在的文件并返回一个TextStream对象&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之八—FSO中文件夹的基本操作&lt;/p&gt;

&lt;p&gt;1、使用fso&lt;/p&gt;

&lt;p&gt;由于fso不是wsh的一部分，所以我们需要建立他的模型&lt;/p&gt;

&lt;p&gt;例如&lt;/p&gt;

&lt;p&gt;set fs=wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;样就建立了fso的模型。如果要释放的话也很简单，&lt;/p&gt;

&lt;p&gt;set fs=nothing&lt;/p&gt;

&lt;p&gt;2、使用文件夹&lt;/p&gt;

&lt;p&gt;在创建前，我们一般需要检查该文件夹是否存在例如：&lt;/p&gt;

&lt;p&gt;dim fs,s //定义fs、s两个变量&lt;/p&gt;

&lt;p&gt;set fs=wscript.createobject(“scripting.filesystemobject”) //fs为FSO实例&lt;/p&gt;

&lt;p&gt;if (fs.folderexists(“c:&quot;temp”)) then //判断c:&quot;temp文件夹是否存在&lt;/p&gt;

&lt;p&gt;s=”is available”&lt;/p&gt;

&lt;p&gt;else&lt;/p&gt;

&lt;p&gt;s=”not exist”&lt;/p&gt;

&lt;p&gt;set foldr=fs.createfolder(“c:&quot;temp”) //不存在则建立&lt;/p&gt;

&lt;p&gt;end if&lt;/p&gt;

&lt;p&gt;拷贝：&lt;/p&gt;

&lt;p&gt;注意：如果c:&quot;data 和d:&quot;data都存在，脚本会出错，复制也就会停止，如果要强制覆盖，使用fs.copyfolder “c:&quot;data”&lt;/p&gt;

&lt;p&gt;“d:&quot;data”，true&lt;/p&gt;

&lt;p&gt;移动：&lt;/p&gt;

&lt;p&gt;set fs=wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;fs.movefolder “c:&quot;data” “d:&quot;data”&lt;/p&gt;

&lt;p&gt;我们可以使用统配符，来方便操作：&lt;/p&gt;

&lt;p&gt;例如， fs.movefolder :c:&quot;data&quot;te*” , “d:&quot;working”&lt;/p&gt;

&lt;p&gt;注意：在目的路径最后没有使用“&quot;”也就是说我没有这样写：&lt;/p&gt;

&lt;p&gt;fs.movefolder c:&quot;data&quot;te*” , “d:&quot;working&quot;”&lt;/p&gt;

&lt;p&gt;这样写的话，如果d:&quot;working 目录不存在，windows就不会为我们自动创建这个目录。&lt;/p&gt;

&lt;p&gt;注意：上面我们所举的例子都是在利用fso提供的方法，如果使用folder对象也完全是可以的：&lt;/p&gt;

&lt;p&gt;set fs= wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;set f=fs.getfolder(“c:&quot;data”)&lt;/p&gt;

&lt;p&gt;f.delete //删除文件夹c:&quot;data。如果有子目录，也会被删除&lt;/p&gt;

&lt;p&gt;f.copy “d:&quot;working”,true    //拷贝到d:&quot;working&lt;/p&gt;

&lt;p&gt;f.move “d:&quot;temp”    //移动到d:&quot;temp&lt;/p&gt;

&lt;p&gt;一般指的就是系统文件夹：&quot;windows&quot;system32，&lt;/p&gt;

&lt;p&gt;临时文件夹，windows文件夹，在前几篇的时候，我们提过一下：例如&lt;/p&gt;

&lt;p&gt;set fs=wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;set wshshell=wscript.createobject(“wscript.shell”)&lt;/p&gt;

&lt;p&gt;osdir=wshshell.expandenvironmentstrings(“%systemroot%”)&lt;/p&gt;

&lt;p&gt;set f =fs.getfolder(osdir)&lt;/p&gt;

&lt;p&gt;wscript.echo f&lt;/p&gt;

&lt;p&gt;这个方法使用3种值：&lt;/p&gt;

&lt;p&gt;0 表示windows文件夹，相关常量是windowsfolder&lt;/p&gt;

&lt;p&gt;1 系统文件夹，相关常量是systemfolder&lt;/p&gt;

&lt;p&gt;2 临时目录，相关常量temporaryfolder&lt;/p&gt;

&lt;p&gt;例如：&lt;/p&gt;

&lt;p&gt;set fs=wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;set wfolder=fs.getspecialfolder(0) ‘返回windows目录&lt;/p&gt;

&lt;p&gt;set wfolder=fs.getspecialfolder(1) ‘返回system32&quot;&lt;/p&gt;

&lt;p&gt;set wfolder=fs.getspecialfolder(2)&apos;返回临时目录&lt;/p&gt;

&lt;p&gt;当然，还有简单的方法那就是使用getspecialfolder() 3、特殊文件夹&lt;/p&gt;

&lt;p&gt;set fs=wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;fs.copyfolder “c:&quot;data” “d:&quot;data”&lt;/p&gt;

&lt;p&gt;set fs=wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;fs.deletefolder(“c:&quot;windows”)&lt;/p&gt;

&lt;p&gt;删除：&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之九—妙用SendKeys简化重复操作&lt;/p&gt;

&lt;p&gt;每次开机的时候，你想自动登陆你的QQ或者博客吗？巧妙使用VBS中的SendKeys命令（这个命令的作用就是模拟键盘操作，将一个或多个按键指令发送到指定Windows窗口来控制应用程序运行），可以极大的方便我们的常用操作。其使用格式为：&lt;/p&gt;

&lt;p&gt;Object.SendKeys string其中：&lt;/p&gt;

&lt;p&gt;Object：为WshShell对象，即脚本的第一行为：&lt;/p&gt;

&lt;p&gt;Set WshShell=WScript.CreateObject(&quot;WScript.Shell&quot;)&lt;/p&gt;

&lt;p&gt;将Object替换为WshShell&lt;/p&gt;

&lt;p&gt;“string”：表示要发送的按键指令字符串，需要放在英文双引号中。它包含如下内容：&lt;/p&gt;

&lt;p&gt;1．基本键：一般来说，要发送的按键指令都可以直接用该按键字符本身来表示，例如要发送字母“x”，使用“WshShell.SendKeys&lt;/p&gt;

&lt;p&gt;&quot;x&quot;”即可。当然，也可直接发送多个按键指令，只需要将按键字符按顺序排列在一起即可，例如，要发送按键“cfan”，可以使用&lt;/p&gt;

&lt;p&gt;“WshShell.SendKeys &quot;cfan&quot;”。&lt;/p&gt;

&lt;p&gt;2．特殊功能键：对于需要与Shift、Ctrl、Alt三个控制键组合的按键，SendKeys使用特殊字符来表示：Shift — +；Ctrl   —  ^；Alt — %&lt;/p&gt;

&lt;p&gt;如要发送的组合按键是同时按下Ctrl＋E，需要用WshShell.SendKeys&lt;/p&gt;

&lt;p&gt;&quot;^e&quot;”表示，如果要发送的组合按键是按住Ctrl键的同时按下E与C两个键，这时应使用小括号把字母键括起来，书写格式为“WshShell.SendKeys&lt;/p&gt;

&lt;p&gt;&quot;^(ec)&quot;”，这里要注意它与“WshShell.SendKeys&lt;/p&gt;

&lt;p&gt;&quot;^ec&quot;”的区别，后者表示组合按键是同时按住Ctrl和E键，然后松开Ctrl键，单独按下“C”字母键。&lt;/p&gt;

&lt;p&gt;由于“+”、“^”这些字符用来表示特殊的控制按键了，如何表示这些按键呢？只要用大括号括住这些字符即可。例如，要发送加号“+”，可使用“WshShell.SendKeys&lt;/p&gt;

&lt;p&gt;&quot;{+}&quot;”。另外对于一些不会生成字符的控制功能按键，也同样需要使用大括号括起来按键的名称，例如要发送回车键，需要用“WshShell.SendKeys&lt;/p&gt;

&lt;p&gt;&quot;{ENTER}&quot;”表示，发送向下的方向键用&lt;/p&gt;

&lt;p&gt;“WshShell.SendKeys &quot;{DOWN}&quot;”表示。&lt;/p&gt;

&lt;p&gt;如果需要发送多个重复的单字母按键，不必重复输入该字母，SendKeys允许使用简化格式进行描述，使用格式为“{按键&lt;/p&gt;

&lt;p&gt;数字}”。例如要发送10个字母“x”，则输入“WshShell.SendKeys &quot;{x 10}&quot;”即可。&lt;/p&gt;

&lt;p&gt;例一：WshShell.SendKeys &quot;^{ESC}u&quot;&lt;/p&gt;

&lt;p&gt;代码的含义为：按下Ctrl＋Esc组合键（相当于按Win键）打开“开始”菜单，接着按U键打开“关机”菜单。&lt;/p&gt;

&lt;p&gt;例二：让VBS脚本自动在记事本中输入一行文字“hello, welcome to cfan”。&lt;/p&gt;

&lt;p&gt;Dim WshShell&lt;/p&gt;

&lt;p&gt;Set WshShell=WScript.CreateObject(&quot;WScript.Shell&quot;)&lt;/p&gt;

&lt;p&gt;WshShell.Run &quot;notepad&quot;&lt;/p&gt;

&lt;p&gt;WScript.Sleep 2000&lt;/p&gt;

&lt;p&gt;//本行的含义为是脚本暂停2秒，给notepad一个打开的时间，有时时间太短可能导致后面的字符无法进入编辑区&lt;/p&gt;

&lt;p&gt;WshShell.AppActivate &quot;无标题 - 记事本&lt;/p&gt;

&lt;p&gt;&quot;//AppActivate为寻找可执行程序的标题框，”无标题－记事本”内容你的自己打开看一下&lt;/p&gt;

&lt;p&gt;WshShell.SendKeys &quot;hello, welcome to cfan&quot;&lt;/p&gt;

&lt;p&gt;作业1:让脚本自动输入下面两段小短句&lt;/p&gt;

&lt;p&gt;This is the most wonderful day of my life&lt;/p&gt;

&lt;p&gt;because I&apos;m here with you now&lt;/p&gt;

&lt;p&gt;作业2：让脚本在输入短句后自动关闭记事本，并保存文件名为“test”，注意关闭记事本可以直接使用组合按键Alt＋F4来实现。&lt;/p&gt;

&lt;p&gt;例三：制作能自动定时存盘的记事本&lt;/p&gt;

&lt;p&gt;我们最常用的记事本没有Word、WPS那样的自动定时存盘功能，其实利用VBS脚本再加上SendKeys命令，就能弥补这个遗憾。打开记事本，输入以下内容（为容易描述和分析，把代码分为四个部分）：&lt;/p&gt;

&lt;p&gt;&apos;第一部分：定义变量和对象&lt;/p&gt;

&lt;p&gt;Dim WshShell, AutoSaveTime, TXTFileName&lt;/p&gt;

&lt;p&gt;AutoSaveTime=300000&lt;/p&gt;

&lt;p&gt;Set WshShell=WScript.CreateObject(&quot;WScript.Shell&quot;)&lt;/p&gt;

&lt;p&gt;TXTFileName=InputBox(&quot;请输入你要创建的文件名(不能用中文和纯数字)：&quot;)&lt;/p&gt;

&lt;p&gt;&apos;第二部分：打开并激活记事本&lt;/p&gt;

&lt;p&gt;WshShell.Run &quot;notepad&quot;&lt;/p&gt;

&lt;p&gt;WScript.Sleep 200&lt;/p&gt;

&lt;p&gt;WshShell.AppActivate &quot;无标题 - 记事本&quot;&lt;/p&gt;

&lt;p&gt;&apos;第三部分：用输入的文件名存盘&lt;/p&gt;

&lt;p&gt;WshShell.SendKeys &quot;^s&quot;&lt;/p&gt;

&lt;p&gt;WScript.Sleep 300&lt;/p&gt;

&lt;p&gt;WshShell.SendKeys TXTFileName&lt;/p&gt;

&lt;p&gt;WScript.Sleep 300&lt;/p&gt;

&lt;p&gt;WshShell.SendKeys &quot;%s&quot;&lt;/p&gt;

&lt;p&gt;WScript.Sleep AutoSaveTime&lt;/p&gt;

&lt;p&gt;&apos;第四部分：自动定时存盘&lt;/p&gt;

&lt;p&gt;While WshShell.AppActivate (TXTFileName)=True&lt;/p&gt;

&lt;p&gt;WshShell.SendKeys &quot;^s&quot;&lt;/p&gt;

&lt;p&gt;WScript.Sleep AutoSaveTime&lt;/p&gt;

&lt;p&gt;Wend&lt;/p&gt;

&lt;p&gt;WScript.Quit&lt;/p&gt;

&lt;p&gt;将其保存为记事本.vbs，以后要使用记事本时，都通过双击这个脚本文件来打开。&lt;/p&gt;

&lt;p&gt;程序说明：这个脚本的基本思路是定时向记事本发送Ctrl＋S这个存盘组合键。&lt;/p&gt;

&lt;p&gt;第一部分：定义了脚本中需要用到的变量和对象。“AutoSaveTime”变量用来设置自动存盘间隔，单位为毫秒，这里设置为5分钟。“TXTFileName”变量通过输入框取得你要创建的文本文件名称。&lt;/p&gt;

&lt;p&gt;第二部分：运行记事本，对于Windows本身提供的程序，比如计算器等，可直接在“WshShell.Run”后输入程序名称，如&quot;calc&quot;，对于非系统程序，则可输入完全路径，但要注意使用8.3格式输入，比如“&quot;D:&quot;Progra~1&quot;Tencent&quot;QQ.exe&quot;”。&lt;/p&gt;

&lt;p&gt;第三部分：这里用SendKeys命令执行了这样的操作流程（请注意每个操作之间延时命令的使用）：在记事本中按Ctrl＋S组合键→弹出保存文件的窗口→输入文件名→按Alt＋S组合键进行保存（默认保存在“我的文档”目录）。&lt;/p&gt;

&lt;p&gt;第四部分：定时存盘的关键，通过“While……Wend”这个当条件为“真”时循环命令，实现自动存盘代码“WshShell.SendKeys&lt;/p&gt;

&lt;p&gt;&quot;^s&quot;”和定时代码“WScript.Sleep&lt;/p&gt;

&lt;p&gt;AutoSaveTime”的重复执行。因为不能让这个定时存盘循环一直执行，退出记事本后，必须自动退出脚本并结束循环，所以设计了一个循环判断条件“WshShell.AppActivate&lt;/p&gt;

&lt;p&gt;TXTFileName=True”，当记事本运行中时，可以激活记事本窗口，这个条件运行结果为“True”，定时存盘循环一直执行，退出记事本后，脚本无法激活记事本窗口，就会跳出循环，执行“Wend”后面的“WScript.Quit”退出脚本。&lt;/p&gt;

&lt;p&gt;例四：关机菜单立刻显身&lt;/p&gt;

&lt;p&gt;打开记事本，输入以下命令，并将其保存为1.vbs：&lt;/p&gt;

&lt;p&gt;set WshShell = CreateObject(&quot;WScript.Shell&quot;)&lt;/p&gt;

&lt;p&gt;WshShell.SendKeys &quot;^{ESC}u&quot;&lt;/p&gt;

&lt;p&gt;双击运行它，你会发现关机菜单立刻出现了。&lt;/p&gt;

&lt;p&gt;将“WshShell.SendKeys &quot;^{ESC}u&quot;”改为“WshShell.SendKeys &quot;^+{ESC}&quot;”，运行一下看看是否打开了任务管理器。&lt;/p&gt;

&lt;p&gt;让我们举个例子利用SendKeys自动上网并登陆博客&lt;/p&gt;

&lt;p&gt;将下面的脚本复制到一个文本文件中，并将其文件名命名为：自动登陆.vbs，然后将拨号软件及本脚本一起复制到程序——启动项中，就可以实现自动拨号上网，并登陆到博客上。&lt;/p&gt;

&lt;p&gt;代码如下：&lt;/p&gt;

&lt;p&gt;Set wshshell=CreateObject(&quot;wscript.shell&quot;)&lt;/p&gt;

&lt;p&gt;wshshell.AppActivate &quot;连接 MAE-301U 拨号连接&quot;&lt;/p&gt;

&lt;p&gt;wscript.Sleep 20000&lt;/p&gt;

&lt;p&gt;wshshell.SendKeys &quot;{enter}&quot;&lt;/p&gt;

&lt;p&gt;wshshell.Run &quot;iexplore&quot;&lt;/p&gt;

&lt;p&gt;WScript.Sleep 2000&lt;/p&gt;

&lt;p&gt;wshshell.AppActivate &quot;hao123网址之家—实用网址,搜索大全,尽在www.hao123.com - Microsoft&lt;/p&gt;

&lt;p&gt;Internet Explorer&quot; &apos;引号中的内容修改为你的浏览器打开后标题栏中的内容&lt;/p&gt;

&lt;p&gt;wshshell.SendKeys &quot;%d&quot;&lt;/p&gt;

&lt;p&gt;wshshell.SendKeys &quot;http://passport.baidu.com/?login&quot;&lt;/p&gt;

&lt;p&gt;wshshell.SendKeys &quot;{enter}&quot;&lt;/p&gt;

&lt;p&gt;WScript.Sleep 2000&lt;/p&gt;

&lt;p&gt;wshshell.SendKeys &quot;此处修改为博客帐号&quot;&lt;/p&gt;

&lt;p&gt;wshshell.SendKeys &quot;{tab}&quot;&lt;/p&gt;

&lt;p&gt;wshshell.SendKeys &quot;此处修改为博客密码&quot;&lt;/p&gt;

&lt;p&gt;wshshell.SendKeys &quot;{enter}&quot;&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之十 —— Vbs脚本编程常用的编辑器&lt;/p&gt;

&lt;p&gt;Vbs脚本常用的编辑器当然是notapad，不过这个编辑器的功能当然实在是太弱了一点，其实有很多的专用的脚本编辑器可以大大方便vbs脚本的编写。我常用的有两种：&lt;/p&gt;

&lt;p&gt;1、VBSEDit汉化版&lt;/p&gt;

&lt;p&gt;2、primalscript汉化版，可以对30多种脚本进行编辑&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之十一 ——FSO中文件的基本操作&lt;/p&gt;

&lt;p&gt;一、文件属性：&lt;/p&gt;

&lt;p&gt;在windows中，文件的属性一般用数字来表示：&lt;/p&gt;

&lt;p&gt;0代表normal，即普通文件未设置任何属性。   1代表只读文件。&lt;/p&gt;

&lt;p&gt;2代表隐藏文件。   4代表系统文件。   16代表文件夹或目录。&lt;/p&gt;

&lt;p&gt;32代表存档文件。 1024代表链接或快捷方式。例如：&lt;/p&gt;

&lt;p&gt;set fs=wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;set f=fs.getfile(“d:&quot;index.txt”)&lt;/p&gt;

&lt;p&gt;msgbox f.Attributes ‘attributes函数的作用是显示文件属性&lt;/p&gt;

&lt;p&gt;需要说明的是：msgbox显示的结果往往不是上面说明的数字，而是有关属性代表数字的和。&lt;/p&gt;

&lt;p&gt;二、创建文件：object.createtextfile方法，注意创建前一般需要检查文件是否存在。&lt;/p&gt;

&lt;p&gt;例如：set fso=wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;if fso.fileexists(“c:&quot;kk.txt”) then&lt;/p&gt;

&lt;p&gt;msgbox “文件已存在”&lt;/p&gt;

&lt;p&gt;else&lt;/p&gt;

&lt;p&gt;set f=fso.createtextfile(“c:&quot;kk.txt”)&lt;/p&gt;

&lt;p&gt;end if&lt;/p&gt;

&lt;p&gt;如需要强制覆盖已存在的文件，则在文件名后加true参数。&lt;/p&gt;

&lt;p&gt;三、复制、移动、删除文件：使用copyfile方法、movefile方法、deletefile方法。例如：&lt;/p&gt;

&lt;p&gt;set fso=wscript.createobject(“scripting.filesystemobject”)&lt;/p&gt;

&lt;p&gt;fso.copyfile “c:&quot;kk.txt”,”d:&quot;1&quot;kk.txt”,true   //如上文说述，true代表强制覆盖&lt;/p&gt;

&lt;p&gt;fso.movefile “c:&quot;kk.txt”, “d:&quot;” //移动文件&lt;/p&gt;

&lt;p&gt;fso.deletefile “c:&quot;kk.txt” //删除文件&lt;/p&gt;

&lt;p&gt;四、文件的读写：&lt;/p&gt;

&lt;p&gt;1、打开文件：使用opentextfile方法&lt;/p&gt;

&lt;p&gt;如：set ts=fso.opentextfile(“c:&quot;kk.txt”,1,true)&lt;/p&gt;

&lt;p&gt;说明：第二个参数为访问模式1为只读、2写入、8为追加&lt;/p&gt;

&lt;p&gt;第三个参数指定如文件不存在则创建。&lt;/p&gt;

&lt;p&gt;2、读取文件：read(x)读x个字符；readline读一行；readall全部读取&lt;/p&gt;

&lt;p&gt;如：set ffile=fso.opentextfile(“c:&quot;kk.txt”,1,true)&lt;/p&gt;

&lt;p&gt;value=ffile.read(20)&lt;/p&gt;

&lt;p&gt;line=ffile.readline&lt;/p&gt;

&lt;p&gt;contents=ffile.readall&lt;/p&gt;

&lt;p&gt;3、常见的指针变量：&lt;/p&gt;

&lt;p&gt;atendofstream属性：当处于文件结尾的时候这个属性返回true。一般用循环检测是否到达文件末尾。例如：&lt;/p&gt;

&lt;p&gt;do while ffile.atendofstream&amp;lt;&amp;gt;true&lt;/p&gt;

&lt;p&gt;ffile.read(10)&lt;/p&gt;

&lt;p&gt;loop&lt;/p&gt;

&lt;p&gt;atendofline属性：如果已经到了行末尾，这个属性返回true。&lt;/p&gt;

&lt;p&gt;Column属性(当前字符位置的列号)和line属性(文件当前行号)：在打开一个文件后，行和列指针都被设置为1。&lt;/p&gt;

&lt;p&gt;4、在文件中跳行：skip(x) 跳过x个字符；skipline 跳过一行&lt;/p&gt;

&lt;p&gt;5、在文件中写入字符：可以用2－写入和8－追加的方式来写入&lt;/p&gt;

&lt;p&gt;其方法有：write(x)写入x字符串；writeline(x)写入x代表的一行&lt;/p&gt;

&lt;p&gt;writeblanklines(n) 写入n个空行&lt;/p&gt;

&lt;p&gt;注意：最后一定要使用close方法关闭文件。读文件后一定要关闭，才能以写的方式打开。&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之十二—使用系统对话框&lt;/p&gt;

&lt;p&gt;在VBS脚本设计中，如果能使用windows提供的系统对话框，可以简化脚本的使用难度，使脚本人性化许多，很少有人使用，但VBS并非不能实现这样的功能，方法当然还是利用COM对象。&lt;/p&gt;

&lt;p&gt;1、SAFRCFileDlg.FileSave对象：属性有：FileName —指定默认文件名；FileType —&lt;/p&gt;

&lt;p&gt;指定文件扩展名；OpenFileSaveDlg —显示文件保存框体方法。&lt;/p&gt;

&lt;p&gt;2、SAFRCFileDlg.FileOpen 对象：FileName —默认文件名属性；OpenFileOpenDlg —显示打开文件框体方法。&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;3、UserAccounts.CommonDialog对象：Filter —扩展名属性（&quot;vbs File&lt;/td&gt;
      &lt;td&gt;*.vbs&lt;/td&gt;
      &lt;td&gt;All Files&lt;/td&gt;
      &lt;td&gt;&lt;em&gt;.&lt;/em&gt;&quot;）；&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;FilterIndex —指定&lt;/p&gt;

&lt;p&gt;InitialDir —指定默认的文件夹&lt;/p&gt;

&lt;p&gt;FileName —指定的文件名&lt;/p&gt;

&lt;p&gt;Flags —对话框的类型&lt;/p&gt;

&lt;p&gt;Showopen方法：&lt;/p&gt;

&lt;p&gt;很简单，ok，让我们来举两个简单的例子：&lt;/p&gt;

&lt;p&gt;例一：保存文件&lt;/p&gt;

&lt;p&gt;Set objDialog = CreateObject(&quot;SAFRCFileDlg.FileSave&quot;)&lt;/p&gt;

&lt;p&gt;Set objFSO = CreateObject(&quot;Scripting.FileSystemObject&quot;)&lt;/p&gt;

&lt;p&gt;objDialog.FileName = &quot;test&quot;&lt;/p&gt;

&lt;p&gt;objDialog.FileType = &quot;.txt&quot;&lt;/p&gt;

&lt;p&gt;intReturn = objDialog.OpenFileSaveDlg&lt;/p&gt;

&lt;p&gt;If intReturn Then&lt;/p&gt;

&lt;p&gt;objFSO.CreateTextFile(objDialog.FileName &amp;amp; objdialog.filetype)&lt;/p&gt;

&lt;p&gt;Else&lt;/p&gt;

&lt;p&gt;Wscript.Quit&lt;/p&gt;

&lt;p&gt;End If&lt;/p&gt;

&lt;p&gt;注意：1、SAFRCFileDlg.FileSave对象仅仅是提供了一个方便用户选择的界面，本身并没有保存文件的功能，保存文件还需要使用FSO对象来完成。2、用FileType属性来指定默认的文件类型。3、在调用OpenFileSaveDlg方法时，最好把返回值保存到一变量中，用它可以判断用户按下的是确定还是取消。&lt;/p&gt;

&lt;p&gt;例二：.打开文件&lt;/p&gt;

&lt;p&gt;set objFile = CreateObject(&quot;SAFRCFileDlg.FileOpen&quot;)&lt;/p&gt;

&lt;p&gt;intRet = objFile.OpenFileOpenDlg&lt;/p&gt;

&lt;p&gt;if intret then&lt;/p&gt;

&lt;p&gt;msgbox “文件打开成功！文件名为：” &amp;amp; objFile.filename&lt;/p&gt;

&lt;p&gt;else&lt;/p&gt;

&lt;p&gt;wscript.quit&lt;/p&gt;

&lt;p&gt;end if&lt;/p&gt;

&lt;p&gt;例三：比较复杂的打开文件对话框&lt;/p&gt;

&lt;p&gt;Set objDialog = CreateObject(&quot;UserAccounts.CommonDialog&quot;)&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;objDialog.Filter = &quot;vbs File&lt;/td&gt;
      &lt;td&gt;*.vbs&quot;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;objDialog.InitialDir = &quot;c:&quot;&quot;&lt;/p&gt;

&lt;p&gt;tfile=objDialog.ShowOpen&lt;/p&gt;

&lt;p&gt;if tfile then&lt;/p&gt;

&lt;p&gt;strLoadFile = objDialog.FileName&lt;/p&gt;

&lt;p&gt;msgbox strLoadFile&lt;/p&gt;

&lt;p&gt;else&lt;/p&gt;

&lt;p&gt;wscript.quit&lt;/p&gt;

&lt;p&gt;end if&lt;/p&gt;

&lt;p&gt;说明：在脚本中加入 objDialog.Flags = &amp;amp;H020 看看会出现什么结果。&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之十三 —使用dictionary对象&lt;/p&gt;

&lt;p&gt;VBS中存在一个特殊的对象－dictionnary，是一个集合对象。一般情况霞，我把这个特殊的集合想象为数组，可以使用其中内建的函数完成存储和操纵数据等基本任务，无须担心数据是在哪些行列，而是使用唯一的键进行访问或者是一个只能运行在内存中的数据库，并只有两个字段分别是：key和item，在使用中，字段key是索引字段。&lt;/p&gt;

&lt;p&gt;set sdict=CreateObject(&quot;Scripting.Dictionary&quot;)&lt;/p&gt;

&lt;p&gt;sdict.add &quot;a&quot;,&quot;apple&quot;&lt;/p&gt;

&lt;p&gt;sdict.add &quot;b&quot;,&quot;banana&quot;&lt;/p&gt;

&lt;p&gt;sdict.add &quot;c&quot;,&quot;copy&quot;&lt;/p&gt;

&lt;p&gt;for each key in sdict.keys&lt;/p&gt;

&lt;p&gt;msgbox     &quot;键名&quot; &amp;amp;   key     &amp;amp; &quot;是&quot; &amp;amp; &quot; = &quot; &amp;amp; sdict (key)&lt;/p&gt;

&lt;p&gt;next&lt;/p&gt;

&lt;p&gt;sdict.removeall&lt;/p&gt;

&lt;p&gt;这个脚本很简单，就是定义了一个 dictionary 对象的实例sdict，并加入了三条数据，然后对每一条数据进行了枚举，最后，将对象的实例清空。&lt;/p&gt;

&lt;p&gt;Dictionary 对象的成员概要&lt;/p&gt;

&lt;p&gt;属性和说明&lt;/p&gt;

&lt;p&gt;CompareMode    设定或返回键的字符串比较模式&lt;/p&gt;

&lt;p&gt;Count     只读。返回 Dictionary 里的键/条目对的数量&lt;/p&gt;

&lt;p&gt;Item(key) 设定或返回指定的键的条目值&lt;/p&gt;

&lt;p&gt;Key(key) 设定键值&lt;/p&gt;

&lt;p&gt;方法和说明&lt;/p&gt;

&lt;p&gt;Add(key,item) 增加键/条目对到 Dictionary&lt;/p&gt;

&lt;p&gt;Exists(key) 如果指定的键存在，返回 True，否则返回 False&lt;/p&gt;

&lt;p&gt;Items() 返回一个包含 Dictionary 对象中所有条目的数组&lt;/p&gt;

&lt;p&gt;Keys() 返回一个包含 Dictionary 对象中所有键的数组&lt;/p&gt;

&lt;p&gt;Remove(key) 删除一个指定的键/条目对&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   RemoveAll()   删除全部键/条目对
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Vbs脚本编程简明教程之十四—VBS内置函数&lt;/p&gt;

&lt;p&gt;Abs 函数：返回数的绝对值。&lt;/p&gt;

&lt;p&gt;Array 函数：返回含有数组的变体。&lt;/p&gt;

&lt;p&gt;Asc 函数：返回字符串首字母的 ANSI 字符码。&lt;/p&gt;

&lt;p&gt;Atn 函数：返回数值的反正切。&lt;/p&gt;

&lt;p&gt;CBool 函数：返回已被转换为 Boolean 子类型的变体的表达式。&lt;/p&gt;

&lt;p&gt;CByte 函数：返回已被转换为字节子类型的变体的表达式。&lt;/p&gt;

&lt;p&gt;CCur 函数：返回已被转换为货币子类型的变体的表达式。&lt;/p&gt;

&lt;p&gt;CDate 函数：返回已被转换为日期子类型的变体的表达式。&lt;/p&gt;

&lt;p&gt;CDbl 函数：返回已被转换为双精度子类型的变体的表达式。&lt;/p&gt;

&lt;p&gt;Chr 函数：返回与指定的 ANSI 字符码相关的字符。&lt;/p&gt;

&lt;p&gt;CInt 函数：返回已被转换为整形子类型的变体的表达式。&lt;/p&gt;

&lt;p&gt;CLng 函数；返回已被转换为Long子类型的变体的表达式。&lt;/p&gt;

&lt;p&gt;Cos 函数：返回角度的余弦。&lt;/p&gt;

&lt;p&gt;CreateObject 函数：创建并返回对“自动”对象的引用。&lt;/p&gt;

&lt;p&gt;CSng 函数：返回已被转换为单精度子类型的变体的表达式。&lt;/p&gt;

&lt;p&gt;CStr 函数：返回已被转换为字符串子类型的变体的表达式。&lt;/p&gt;

&lt;p&gt;Date 函数：返回当前系统日期。&lt;/p&gt;

&lt;p&gt;DateAdd 函数：返回的日期已经加上了指定的时间间隔。&lt;/p&gt;

&lt;p&gt;DateDiff 函数：返回两个日期之间的间隔。&lt;/p&gt;

&lt;p&gt;DatePart 函数：返回给定日期的指定部分。&lt;/p&gt;

&lt;p&gt;DateSerial 函数：返回指定年月日的日期子类型的变体。&lt;/p&gt;

&lt;p&gt;DateValue 函数：返回日期子类型的变体。&lt;/p&gt;

&lt;p&gt;Day 函数：返回日期，取值范围为 1 至 31。&lt;/p&gt;

&lt;p&gt;Eval 函数：计算表达式并返回结果。&lt;/p&gt;

&lt;p&gt;Exp 函数：返回 e （自然对数的底）的多少次方。&lt;/p&gt;

&lt;p&gt;Filter 函数：根据指定的筛选条件,返回含有字符串数组子集的、下限为 0 的数组。&lt;/p&gt;

&lt;p&gt;Fix 函数：返回数的整数部分。&lt;/p&gt;

&lt;p&gt;FormatCurrency 函数：返回的表达式为货币值格式，其货币符号采用系统控制面板中定义的。&lt;/p&gt;

&lt;p&gt;FormatDateTime 函数：返回的表达式为日期和时间格式。&lt;/p&gt;

&lt;p&gt;FormatNumber 函数：返回的表达式为数字格式。&lt;/p&gt;

&lt;p&gt;FormatPercent 函数：返回的表达式为百分数（乘以 100）格式，后面有 % 符号。&lt;/p&gt;

&lt;p&gt;GetObject 函数：返回从文件对“自动”对象的引用。&lt;/p&gt;

&lt;p&gt;GetRef 函数：返回对能够绑定到一事件的过程的引用。&lt;/p&gt;

&lt;p&gt;Hex 函数：返回一字符串，代表一个数的十六进制值。&lt;/p&gt;

&lt;p&gt;Hour 函数：返回表示钟点的数字，取值范围为 0 至 23。&lt;/p&gt;

&lt;p&gt;InputBox 函数：在对话框中显式一提示，等待用户输入文本或单击按钮，并返回文本框的内容。&lt;/p&gt;

&lt;p&gt;InStr 函数：返回一个字符串在另一个字符串中首次出现的位置。&lt;/p&gt;

&lt;p&gt;InStrRev 函数；返回一个字符串在另一个字符串中出现的位置，但是从字符串的尾部算起。&lt;/p&gt;

&lt;p&gt;Int 函数：返回数的整数部分。&lt;/p&gt;

&lt;p&gt;IsArray 函数：返回 Boolean 值，反映变量是否为数组。&lt;/p&gt;

&lt;p&gt;IsDate 函数：返回 Boolean 值，反映表达式能否转换为日期。&lt;/p&gt;

&lt;p&gt;IsEmpty 函数：返回 Boolean 值，反映变量是否已被初始化。&lt;/p&gt;

&lt;p&gt;IsNull 函数：返回 Boolean 值，反映表达式是否含有无效数据(Null)。&lt;/p&gt;

&lt;p&gt;IsNumeric 函数：返回 Boolean 值，反映表达式能否转换为数字。&lt;/p&gt;

&lt;p&gt;IsObject 函数：返回 Boolean 值，反映表达式是否引用了有效的“自动”对象。&lt;/p&gt;

&lt;p&gt;Join 函数：返回通过连接许多含有数组的子串而创建的字符串。&lt;/p&gt;

&lt;p&gt;LBound 函数；返回指定维数数组的最小有效下标。&lt;/p&gt;

&lt;p&gt;LCase 函数：返回的字符串已被转换为小写字母。&lt;/p&gt;

&lt;p&gt;Left 函数：返回字符串最左边的指定数量的字符。&lt;/p&gt;

&lt;p&gt;Len 函数：返回字符串中的字符数或存储变量所需的字节数。&lt;/p&gt;

&lt;p&gt;LoadPicture 函数：返回图片对象。只用于 32 位平台。&lt;/p&gt;

&lt;p&gt;Log 函数：返回数的自然对数。&lt;/p&gt;

&lt;p&gt;LTrim 函数；返回去掉前导空格的字符串。&lt;/p&gt;

&lt;p&gt;Mid 函数：从字符串中返回指定数量的字符。&lt;/p&gt;

&lt;p&gt;Minute 函数：返回分钟数，取值范围为 0 至 59。&lt;/p&gt;

&lt;p&gt;Month 函数：返回表示月份的数，取值范围为 1 至 12。&lt;/p&gt;

&lt;p&gt;MonthName 函数：返回表示月份的字符串。&lt;/p&gt;

&lt;p&gt;MsgBox 函数：在对话框中显示消息，等待用户单击按钮，并返回表示用户所击按钮的数值。&lt;/p&gt;

&lt;p&gt;Now 函数：返回计算机的当前系统日期和时间。&lt;/p&gt;

&lt;p&gt;Oct 函数：返回表示该数八进制数值的字符串。&lt;/p&gt;

&lt;p&gt;Replace 函数：返回一字符串，其中指定的子串已被另一个子串替换了规定的次数。&lt;/p&gt;

&lt;p&gt;RGB 函数：返回代表 RGB 颜色值的数字。&lt;/p&gt;

&lt;p&gt;Right 函数：返回字符串最右边的指定数量的字符。&lt;/p&gt;

&lt;p&gt;Rnd 函数：返回随机数。&lt;/p&gt;

&lt;p&gt;Round 函数：返回指定位数、四舍五入的数。&lt;/p&gt;

&lt;p&gt;RTrim 函数：返回去掉尾部空格的字符串副本。&lt;/p&gt;

&lt;p&gt;ScriptEngine 函数：返回反映使用中的脚本语言的字符串。&lt;/p&gt;

&lt;p&gt;ScriptEngineBuildVersion 函数：返回使用中的脚本引擎的编译版本号。&lt;/p&gt;

&lt;p&gt;ScriptEngineMajorVersion 函数：返回使用中的脚本引擎的主版本号。&lt;/p&gt;

&lt;p&gt;ScriptEngineMinorVersion 函数：返回使用中的脚本引擎的次版本号。&lt;/p&gt;

&lt;p&gt;Second 函数：返回秒数，取值范围为 0 至 59。&lt;/p&gt;

&lt;p&gt;Sgn 函数：返回反映数的符号的整数。&lt;/p&gt;

&lt;p&gt;Sin 函数：返回角度的正弦值。&lt;/p&gt;

&lt;p&gt;Space 函数：返回由指定数量的空格组成的字符串。&lt;/p&gt;

&lt;p&gt;Split 函数：返回下限为 0 的、由指定数量的子串组成的一维数组。&lt;/p&gt;

&lt;p&gt;Sqr 函数：返回数的平方根。&lt;/p&gt;

&lt;p&gt;StrComp 函数：返回反映字符串比较结果的数值。&lt;/p&gt;

&lt;p&gt;String 函数：返回指定长度的重复字符串。&lt;/p&gt;

&lt;p&gt;StrReverse 函数：返回一字符串，其中字符的顺序与指定的字符串中的顺序相反。&lt;/p&gt;

&lt;p&gt;Tan 函数：返回角度的正切值。&lt;/p&gt;

&lt;p&gt;Time 函数：返回表示当前系统时间的“日期”子类型的“变体”。&lt;/p&gt;

&lt;p&gt;Timer 函数：返回时经子夜 12：00 AM 后的秒数。&lt;/p&gt;

&lt;p&gt;TimeSerial 函数：返回含有指定时分秒时间的日期子类型的变体。&lt;/p&gt;

&lt;p&gt;TimeValue 函数：返回含有时间的日期子类型的变体。&lt;/p&gt;

&lt;p&gt;Trim 函数：返回去掉前导空格或尾部空格的字符串副本。&lt;/p&gt;

&lt;p&gt;TypeName 函数：返回一字符串，它提供了关于变量的变体子类型信息。&lt;/p&gt;

&lt;p&gt;UBound 函数：返回指定维数数组的最大有效下标。&lt;/p&gt;

&lt;p&gt;UCase 函数：返回的字符串已经被转换为大写字母。&lt;/p&gt;

&lt;p&gt;VarType 函数：返回标识变体子类型的数值。&lt;/p&gt;

&lt;p&gt;Weekday 函数：返回表示星期几的数值。&lt;/p&gt;

&lt;p&gt;WeekdayName 函数：返回表示星期几的字符串。&lt;/p&gt;

&lt;p&gt;Year 函数：返回表示年份的数值。&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之十五——响应事件&lt;/p&gt;

&lt;p&gt;什么是事件？在我看来，事件就象我们手机上的闹钟，闹钟一响，我们就要去做某些特定的事情。或者这样说，事件就像警钟，当程序运行时，有特殊的事情发生，就会激发事件，事件本身就是一条消息，如果你编写的脚本要对事件进行处理，就需要一个特殊的过程或者函数来接受和处理事件。那么这个特殊的过程或者函数在程序运行时，就不断的监听，看系统是否传来了相应的事件，一旦接受到事件，脚本对此作出反应。&lt;/p&gt;

&lt;p&gt;那么事件是从那里来的呢？是否需要我们在脚本中对事件进行编写呢？一般情况下，事件是某个程序在运行中的特殊状态发出的，我们不需要对事件进行编写，只需要编写处理事件的函数。比如说我们用vbs建立了ie的一个实例，那么当ie的窗口被关闭的时候，就会激发出一个叫做OnQuit的事件。&lt;/p&gt;

&lt;p&gt;是不是脚本自然而然就能接受事件并进行处理呢？我们说不是的，在创建对象的时候，我们将使用WSH的createobject命令，例如：&lt;/p&gt;

&lt;p&gt;Set objie=Wscript.createobject(“internetexplorer.application”,”event_”)&lt;/p&gt;

&lt;p&gt;注意到了吗？多了一个参数，这个参数的作用是什么呢？它叫做事件接收端，当脚本连接的对象包含事件时，如果对象调用的事件是OnBegin，那么WSH将会在脚本中调用一个event_OnBegin的事件处理程序。当然事件接受端并不是固定的，如果对象将其定义为MyObj_的话，那么事件处理程序将是：MyObj_OnBegin。&lt;/p&gt;

&lt;p&gt;是否很熟悉？在打造个性化QQ一讲中，曾经出现过Window_OnSize(cx,cy)函数，它其实就是一个事件处理程序。&lt;/p&gt;

&lt;p&gt;让我们来举个实际的例子完整的看看事件的处理过程：&lt;/p&gt;

&lt;p&gt;Set objie=WScript.CreateObject(&quot;InternetExplorer.Application&quot;,&quot;event_&quot;)&lt;/p&gt;

&lt;p&gt;objie.Visible=True&lt;/p&gt;

&lt;p&gt;MsgBox &quot;请关闭浏览器窗口看看效果！&quot;,vbSystemModal&lt;/p&gt;

&lt;p&gt;Wscript.sleep 6000&lt;/p&gt;

&lt;p&gt;MsgBox &quot;现在已经正常关闭了&quot;&lt;/p&gt;

&lt;p&gt;Sub event_onquit()&lt;/p&gt;

&lt;p&gt;MsgBox &quot;您确定要关闭浏览器吗？&quot;,vbSystemModal&lt;/p&gt;

&lt;p&gt;End Sub&lt;/p&gt;

&lt;p&gt;这段脚本打开了一个IE窗口，然后要求你关闭IE窗口，当你关闭窗口的时候，自动调用事件响应程序。&lt;/p&gt;

&lt;p&gt;Vbs脚本编程简明教程之十六——访问ADO数据库&lt;/p&gt;

&lt;p&gt;ADO是Microsoft提供和建议使用的新型数据访问接口，它是建立OLEDB之上的一个抽象层。微软公司在操作系统中默认提供了 Access 的 ODBC 驱动程序以及 JET 引擎，&lt;/p&gt;

&lt;p&gt;一、对ADO对象的主要操作，一般包括6个方面：&lt;/p&gt;

&lt;p&gt;1.连接到数据源。通常使用ADO的Connection对象。一般使用相应的属性打开到数据源的连接，设置游标的位置，设置默认的当前数据库，设置将使用的OLEDBProvider，直接提交SQL脚本等。&lt;/p&gt;

&lt;p&gt;2.向数据源提交命令。通常涉及ADO的Command对象。可查询数据库并返回结果在Recordset对象中。&lt;/p&gt;

&lt;p&gt;3.执行SELECT查询命令。在提交SQL脚本的任务时，不用创建一个Command对象，就可完成查询。&lt;/p&gt;

&lt;p&gt;4.可以通过ADO的Recordset对象对结果进行操作。&lt;/p&gt;

&lt;p&gt;5.更新数据到物理存储。&lt;/p&gt;

&lt;p&gt;6.提供错误检测。通常涉及ADO的Error对象。&lt;/p&gt;

&lt;p&gt;二、ADO中主要对象的功能&lt;/p&gt;

&lt;p&gt;Recordset对象，用来封装查询的结果。&lt;/p&gt;

&lt;p&gt;Field对象，用来表达一行结果中各子段的类型和值。&lt;/p&gt;

&lt;p&gt;Error对象，用来检测和判断在数据库操作中出现的错误，比如连接失败。&lt;/p&gt;

&lt;p&gt;在ADO中，许多对象名后多了一个&quot;s&quot;，比如Error-&amp;gt;Errors，Field-&amp;gt;Fields等等。添加&quot;s&quot;意味着是相应对象的Collection（集合）对象，比如Errors是Error对象的Collection对象。Collection有点像数组（Array），但不同的是，Collection可以以不同类型的数据或对象作为自己的元素，而数组中的各元素通常都是相同类型的。所以，在看到一个对象名最后是&quot;s&quot;，通常表明这是一个Collection对象，比如Errors中的各元素是由Error对象的实例组成的。&lt;/p&gt;

&lt;p&gt;三、具体应用&lt;/p&gt;

&lt;p&gt;1、创建mdb数据库&lt;/p&gt;

&lt;p&gt;ADOX 是ADO 对象的扩展库。它可用于创建、修改和删除模式对象，如数据库和表格等。&lt;/p&gt;

&lt;p&gt;其常用的对象有：Catalog—&amp;gt;创建数据库。Column—&amp;gt;表示表、索引或关键字的列。&lt;/p&gt;

&lt;p&gt;Key—&amp;gt;表示数据库表中的关键字。&lt;/p&gt;

&lt;p&gt;常用的方法有： Append 将对象添加到其集合。Delete 删除集合中的对象。&lt;/p&gt;

&lt;p&gt;set cat= createobject(&quot;ADOX.Catalog&quot;)&lt;/p&gt;

&lt;p&gt;cat.Create &quot;Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:&quot;shujuku.mdb&quot;&lt;/p&gt;

&lt;p&gt;Set tbl=createobject(&quot;ADOX.Table&quot;)&lt;/p&gt;

&lt;p&gt;tbl.Name =&quot;MyTable&quot;&lt;/p&gt;

&lt;p&gt;tbl.Columns.Append &quot;姓名&quot;, 202 &apos;adInteger&lt;/p&gt;

&lt;p&gt;tbl.Columns.Append &quot;性别&quot;, 3 &apos;adInteger&lt;/p&gt;

&lt;p&gt;tbl.Columns.Append &quot;工作单位&quot;, 202 ,50 &apos;adVarWChar&lt;/p&gt;

&lt;p&gt;cat.Tables.Append tbl&lt;/p&gt;

&lt;p&gt;不过你要操纵数据库就连一个数据库也不建，未免懒惰了点，用代码虽然可以完成，但是我觉得对数据约束完成的比较困难，本代码也就是示范个例子，并不推荐使用此类方法。&lt;/p&gt;

&lt;p&gt;2、打开数据库&lt;/p&gt;

&lt;p&gt;Provider=″Provider=Microsoft.Jet.OLEDB.4.0 ; Data Source=&quot;&lt;/p&gt;

&lt;p&gt;Set Objconn = createobject(&quot;ADODB.Connection&quot;)&lt;/p&gt;

&lt;p&gt;Objconn.Open Provider &amp;amp; &quot;数据库名称&quot;&lt;/p&gt;

&lt;p&gt;3、创建记录集&lt;/p&gt;

&lt;p&gt;Set Objrs = CreateObject(&quot;ADODB.Recordset&quot;)&lt;/p&gt;

&lt;p&gt;4、执行SQL查询语句&lt;/p&gt;

&lt;p&gt;Sql=&quot;SQL查询语句&quot; &apos;例如：Select count(*) from table1&lt;/p&gt;

&lt;p&gt;Set objrs = objconn.execute(sql)&lt;/p&gt;

&lt;p&gt;一般情况下，我们将绝大多数的操作转化为SQL语句完成。&lt;/p&gt;

&lt;p&gt;常用的SQL语句&lt;/p&gt;

&lt;p&gt;在学习SQL语句之前，让我们先来对数据库做一个基本的了解。一个数据库中可能包含了很多个基本单位叫做表。表格被分为“行”和“列”。每一行代表表的一个单独组成部分，每一列代表相同性质的一组数据。举例来说，如果我们有一个记载顾客资料的表格，行包括姓、名、地址、城市、国家、生日等。而一列则代表了所有的地址或者国家等。&lt;/p&gt;

&lt;p&gt;一、建立数据表，我们前边说过利用ADOX.Catalog建立数据库和数据表的方法，但是用的似乎不是很多，一般情况下，如果我们需要在数据库中动态建立一个表，我们将工作交给SQL语句来做，其基本语法是：&lt;/p&gt;

&lt;p&gt;CREATE TABLE &lt;a href=&quot;[列名1] 数据类型 , [列名2] 数据类型,...&quot;&gt;表格名&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;例如我们要建立一个基本顾客表：&lt;/p&gt;

&lt;p&gt;Create table &lt;a href=&quot;[姓名] text（8）, [性别] text（2），[住址] text(30)&quot;&gt;顾客表&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;二、插入数据项&lt;/p&gt;

&lt;p&gt;insert into [数据表名称] (数据项1,数据项2,…) values (值1,值2,…)&lt;/p&gt;

&lt;p&gt;insert into语句用来添加新的数据到数据库中的指定表。通过(数据项1,数据项2,…) values (值1,值2,…)来为新添加的数据赋初值。&lt;/p&gt;

&lt;p&gt;三、删除数据项&lt;/p&gt;

&lt;p&gt;delete from [数据表名称] where [数据项1] like [值1] and/or [数据项2] like [值2]&lt;/p&gt;

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

&lt;p&gt;四、更新数据项&lt;/p&gt;

&lt;p&gt;update [数据表名称] set 数据项1=值1,数据项2=值2,… where [数据项1] like [值1] and/or [数据项2] like&lt;/p&gt;

&lt;p&gt;[值2] …&lt;/p&gt;

&lt;p&gt;该语句可以修改数据库中指定数据表内的指定数据，如果不是用where限定条件就表示修改该表内所有的数据条目。&lt;/p&gt;

&lt;p&gt;五、查询数据项&lt;/p&gt;

&lt;p&gt;select [数据内容] from [数据表名称] where [数据项1] like [值1] and/or [数据项2] like [值2] …&lt;/p&gt;

&lt;p&gt;order by [数据项] asc/desc&lt;/p&gt;

&lt;p&gt;[数据内容]部分表示所要选取的表格中的数据项，使用*表示选取全部。[数据表名称]表示要从哪一个表格中选取，如果你没有接触过数据库可能很难了解什么是数据表格，没关系，我将在后面用到它的时候再说明。where表示选取的条件，使用like表示相等，也支持&amp;gt;=这样的判断符号，同时使用多个条件进行选取时中间要使用and进行连接。order&lt;/p&gt;

&lt;p&gt;by决定数据的排列顺序，asc表示按照[数据项]中的数据顺序排列，desc表示倒序，默认情况为顺序。select语句中除select和from之外其它均为可选项，如果都不填写表示选取该数据表中的全部数据。例如：下面的语句查询某数据库中表名称为：testtable中姓名为“张三”的nickname字段和email字段。&lt;/p&gt;

&lt;p&gt;SELECT nickname,email FROM testtable WHERE name=&apos;张三&apos;&lt;/p&gt;

&lt;p&gt;(一) 选择列表&lt;/p&gt;

&lt;p&gt;选择列表(select_list)指出所查询列，它可以是一组列名列表、星号、表达式、变量(包括局部变量和全局变量)等构成。&lt;/p&gt;

&lt;p&gt;1、选择所有列&lt;/p&gt;

&lt;p&gt;例如，下面语句显示testtable表中所有列的数据：&lt;/p&gt;

&lt;p&gt;SELECT * FROM testtable&lt;/p&gt;

&lt;p&gt;2、选择部分列并指定它们的显示次序查询结果集合中数据的排列顺序与选择列表中所指定的列名排列顺序相同。&lt;/p&gt;

&lt;p&gt;例如：SELECT nickname,email FROM testtable&lt;/p&gt;

&lt;p&gt;3、更改列标题&lt;/p&gt;

&lt;p&gt;在选择列表中，可重新指定列标题。定义格式为：列标题=列名&lt;/p&gt;

&lt;p&gt;列名列标题如果指定的列标题不是标准的标识符格式时，应使用引号定界符，例如，下列语句使用汉字显示列标题：&lt;/p&gt;

&lt;p&gt;SELECT 昵称=nickname,电子邮件=email FROM testtable&lt;/p&gt;

&lt;p&gt;(二) FROM子句指定SELECT语句查询的表。&lt;/p&gt;

&lt;p&gt;最多可指定256个表，它们之间用逗号分隔。如果选择列表中存在同名列，这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列，在查询两个表中的cityid时应加以限定。&lt;/p&gt;

&lt;p&gt;(三) WHERE子句设置查询条件&lt;/p&gt;

&lt;p&gt;WHERE子句设置查询条件，过滤掉不需要的数据行。例如下面语句查询年龄大于20的数据：&lt;/p&gt;

&lt;p&gt;SELECT * FROM usertable WHERE age&amp;gt;20&lt;/p&gt;

&lt;p&gt;WHERE子句可包括各种条件运算符：&lt;/p&gt;

&lt;p&gt;比较运算符(大小比较)：&amp;gt;、&amp;gt;=、=、&amp;lt;、&amp;lt;=、&amp;lt;&amp;gt;、!&amp;gt;、!&amp;lt;&lt;/p&gt;

&lt;p&gt;范围运算符(表达式值是否在指定的范围)：BETWEEN…AND…&lt;/p&gt;

&lt;p&gt;NOT BETWEEN…AND…&lt;/p&gt;

&lt;p&gt;列表运算符(判断表达式是否为列表中的指定项)：IN (项1,项2……)&lt;/p&gt;

&lt;p&gt;NOT IN (项1,项2……)&lt;/p&gt;

&lt;p&gt;模式匹配符(判断值是否与指定的字符通配格式相符):LIKE、NOT LIKE&lt;/p&gt;

&lt;p&gt;空值判断符(判断表达式是否为空)：IS NULL、NOT IS NULL&lt;/p&gt;

&lt;p&gt;逻辑运算符(用于多条件的逻辑连接)：NOT、AND、OR&lt;/p&gt;

&lt;p&gt;1、范围运算符例：age BETWEEN 10 AND 30相当于age&amp;gt;=10 AND age&amp;lt;=30&lt;/p&gt;

&lt;p&gt;2、列表运算符例：country IN (&apos;Germany&apos;,&apos;China&apos;)&lt;/p&gt;

&lt;p&gt;3、模式匹配符例：常用于模糊查找，它判断列值是否与指定的字符串格式相匹配。可用于char、&lt;/p&gt;

&lt;p&gt;varchar、text、ntext、datetime和smalldatetime等类型查询。&lt;/p&gt;

&lt;p&gt;可使用以下通配字符：&lt;/p&gt;

&lt;p&gt;百分号%：可匹配任意类型和长度的字符，如果是中文，请使用两个百分号即%%。&lt;/p&gt;

&lt;p&gt;下划线_：匹配单个任意字符，它常用来限制表达式的字符长度。&lt;/p&gt;

&lt;p&gt;方括号[]：指定一个字符、字符串或范围，要求所匹配对象为它们中的任一个。&lt;/p&gt;

&lt;p&gt;[^]：其取值也[] 相同，但它要求所匹配对象为指定字符以外的任一个字符。&lt;/p&gt;

&lt;p&gt;例如：&lt;/p&gt;

&lt;p&gt;限制以Publishing结尾，使用LIKE &apos;%Publishing&apos;&lt;/p&gt;

&lt;p&gt;限制以A开头：LIKE &apos;[A]%&apos;&lt;/p&gt;

&lt;p&gt;限制以A开头外：LIKE &apos;[^A]%&apos;&lt;/p&gt;

&lt;p&gt;4、空值判断符例WHERE age IS NULL&lt;/p&gt;

&lt;p&gt;5、逻辑运算符：优先级为NOT、AND、OR&lt;/p&gt;

&lt;p&gt;最后，让我们用一个简单的例子结束这篇教程：&lt;/p&gt;

&lt;p&gt;Objku = InputBox(&quot;请输入单位数据库的路径&quot;,&quot;默认位置&quot;,&quot;d:&quot;jbqk.mdb&quot;)&lt;/p&gt;

&lt;p&gt;Set Objconn = createobject(&quot;adodb.connection&quot;)&lt;/p&gt;

&lt;p&gt;Objconn.open =&quot;provider=Microsoft.Jet.OLEDB.4.0;Data Source=&quot; &amp;amp; Objku&lt;/p&gt;

&lt;p&gt;sql = &quot;CREATE TABLE [单位资料](ID Autoincrement PRIMARY KEY,[姓名] text(8),[性别]&lt;/p&gt;

&lt;p&gt;text(2),[科室] text(6),[住址] text(30))&quot;&lt;/p&gt;

&lt;p&gt;Objconn.execute(sql)&lt;/p&gt;

&lt;p&gt;sql = &quot;INSERT INTO &lt;a href=&quot;[姓名],[性别],[科室],[住址]&quot;&gt;单位资料&lt;/a&gt; VALUES(&apos;张三&apos;,&apos;男&apos;,&apos;行管科&apos;,&apos;解放路12号&apos;)&quot;&lt;/p&gt;

&lt;p&gt;Objconn.execute(sql)&lt;/p&gt;

&lt;p&gt;sql = &quot;INSERT INTO &lt;a href=&quot;[姓名],[性别],[科室],[住址]&quot;&gt;单位资料&lt;/a&gt; VALUES(&apos;李斯&apos;,&apos;女&apos;,&apos;市场科&apos;,&apos;五一路12号&apos;)&quot;&lt;/p&gt;

&lt;p&gt;Objconn.execute(sql)&lt;/p&gt;

&lt;p&gt;sql = &quot;DELETE FROM [单位资料] WHERE [姓名] = &apos;张三&apos; &quot;&lt;/p&gt;

&lt;p&gt;Objconn.execute(sql)&lt;/p&gt;

&lt;p&gt;sql = &quot;UPDATE [单位资料]&quot;&lt;/p&gt;

&lt;p&gt;sql = &quot;SELECT COUNT(ID) FROM [单位资料]&quot;&lt;/p&gt;

&lt;p&gt;Vbs调用MsAgent组件，很有趣&lt;/p&gt;

&lt;p&gt;Microsoft Agent是微软公司发布的一项代理软件开发技术，我们知道，在Office帮助系统中有一种叫作Office助手的代理软件，但其只允许Office各个组件调用，Agent动画人物可由任何Windows程序调用；&lt;/p&gt;

&lt;p&gt;Agent支持文字气球和输入提示条，在输出语音的同时把文字输出至一个卡通式文字气球中。如果电脑系统中安装有Agent语音识别引擎，当用户可以通过声卡、麦克风与用户交谈。下午无事，就尝试着写了一段简单的代码调用MsAgent：&lt;/p&gt;

&lt;p&gt;GenieID = &quot;Genie&quot;&lt;/p&gt;

&lt;p&gt;GenieACS = &quot;genie.acs&quot;&lt;/p&gt;

&lt;p&gt;ScriptComplete=0&lt;/p&gt;

&lt;p&gt;Set AgentControl = WScript.CreateObject(&quot;Agent.Control.2&quot;,&quot;agent_&quot;)&lt;/p&gt;

&lt;p&gt;AgentControl.Connected = True&apos;连接控件&lt;/p&gt;

&lt;p&gt;AgentControl.Characters.Load GenieID,GenieACS&lt;/p&gt;

&lt;p&gt;Set Genie = AgentControl.Characters(GenieID)&lt;/p&gt;

&lt;p&gt;Genie.LanguageID = &amp;amp;H409&lt;/p&gt;

&lt;p&gt;Genie.MoveTo 900, 600&lt;/p&gt;

&lt;p&gt;Genie.Show&lt;/p&gt;

&lt;p&gt;Genie.MoveTo 900, 0&lt;/p&gt;

&lt;p&gt;timespeak=&quot;good &quot; &amp;amp; GetTimeOfDay()&lt;/p&gt;

&lt;p&gt;Genie.Speak(timespeak)&lt;/p&gt;

&lt;p&gt;Genie.Play &quot;Acknowledge&quot;     &apos;承认&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;眨眼&quot;)&lt;/p&gt;

&lt;p&gt;Genie.Play &quot;Blink&quot;     &apos;眨眼&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;i love you&quot;)&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;回复动作&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;RestPose&quot;)     &apos;回復动作&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;向上&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;GestureUp&quot;)     &apos;向上&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;向下&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;GestureDown&quot;)     &apos;向下&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;伸出左手&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;GestureLeft&quot;)     &apos; 伸出左手&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;伸出右手&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;GestureRight&quot;)     &apos; 伸出右手&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;叹气&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Sad&quot;)     &apos;嘆气&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;惊奇&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Surprised&quot;)     &apos;惊奇&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;握掌&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Pleased&quot;)     &apos;握掌&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;喇叭&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Announce&quot;)     &apos;喇叭&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;眯眼&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Blink&quot;)     &apos;瞇眼&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;无奈&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Decline&quot;)     &apos;无奈&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;抓头&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Confused&quot;)     &apos;抓头&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;鼓掌&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Congratulate&quot;)     &apos;奖盃&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;回手&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Wave&quot;)     &apos;挥手&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;惊讶&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Alert&quot;)     &apos;惊讶&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;魔术棒1&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;DoMagic1&quot;)     &apos;魔术棒-1&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;魔术棒2&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;DoMagic2&quot;)     &apos;魔术棒-2&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;摊手&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Explain&quot;)     &apos;摊手&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;敲门&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;GetAttention&quot;)     &apos;敲门&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;GetAttentionContinued&quot;)     &apos;敲门-敲&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;GetAttentionReturn&quot;)     &apos;敲门-放下&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Greet&quot;)     &apos;弯腰&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Idle2_1&quot;)     &apos;观察魔术棒&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Idle2_2&quot;)     &apos;两手在腹前交叉&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Idle3_1&quot;)     &apos;打呵欠&lt;/p&gt;

&lt;p&gt;Genie.Speak(&quot;向上看&quot;)&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;LookUp&quot;)     &apos;上看&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;LookDown&quot;)     &apos;下看&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;LookLeft&quot;)     &apos;左看&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;LookRight&quot;)     &apos;右看&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;MoveUp&quot;)     &apos;上移&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;MoveDown&quot;)     &apos;下移&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;MoveLeft&quot;)     &apos;左移&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;MoveRight&quot;)     &apos;右移&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Process&quot;)     &apos;魔法调配&lt;/p&gt;

&lt;p&gt;genie.Play(&quot;Read&quot;)     &apos;阅读&lt;/p&gt;

&lt;p&gt;Do     &apos;此处存疑，高手请看最后&lt;/p&gt;

&lt;p&gt;WScript.Sleep 1000&lt;/p&gt;

&lt;p&gt;Loop Until ScriptComplete&lt;/p&gt;

&lt;p&gt;Function GetTimeOfDay()&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   Dim TimeOfDay

   Dim h

   h = Hour(Now())

   If h &amp;lt; 12 Then

       TimeOfDay = &quot;Morning&quot;

   ElseIf h &amp;lt; 17 Then

       TimeOfDay = &quot;Afternoon&quot;

   Else

       TimeOfDay = &quot;Evening&quot;

   End If

   GetTimeOfDay = TimeOfDay
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;End Function&lt;/p&gt;

&lt;p&gt;Sub agent_dblclick(ByVal CharacterID, ByVal Button, ByVal Shift, ByVal X, ByVal&lt;/p&gt;

&lt;p&gt;Y)&lt;/p&gt;

&lt;p&gt;Genie.StopAll&lt;/p&gt;

&lt;p&gt;MsgBox &quot;白白，再见了！&quot;&lt;/p&gt;

&lt;p&gt;WScript.Quit&lt;/p&gt;

&lt;p&gt;End Sub&lt;/p&gt;

&lt;p&gt;本来代码写的就没有什么难度，可是写完之后，每次可爱的小人总是一闪而过，屏幕上什么也看不见，在网络上查找也找不出原因，我实验了好多次，终于发觉了加红的那段代码必不可少，程序异步执行，没有最后的代码，程序没有执行完就退出了&lt;/p&gt;

&lt;p&gt;Reference:&lt;a href=&quot;http://blog.csdn.net/yjbnew/article/details/6732039&quot;&gt;Vbs脚本编程简明教程&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Emacs Tutorial</title>
   <link href="/2014/07/12/emacs-tutorial/"/>
   <updated>2014-07-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/07/12/emacs-tutorial</id>
   <content type="html">&lt;ol id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#readme&quot; id=&quot;markdown-toc-readme&quot;&gt;README&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#abcs&quot; id=&quot;markdown-toc-abcs&quot;&gt;ABCs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#frame-vs-window&quot; id=&quot;markdown-toc-frame-vs-window&quot;&gt;frame VS window&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#help-summary&quot; id=&quot;markdown-toc-help-summary&quot;&gt;Help Summary&lt;/a&gt;        &lt;ol&gt;
          &lt;li&gt;&lt;a href=&quot;#three-help-utililies&quot; id=&quot;markdown-toc-three-help-utililies&quot;&gt;Three help utililies&lt;/a&gt;&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#killing-and-deleting&quot; id=&quot;markdown-toc-killing-and-deleting&quot;&gt;Killing and Deleting&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#useful-keys&quot; id=&quot;markdown-toc-useful-keys&quot;&gt;Useful keys&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#universal-arguments&quot; id=&quot;markdown-toc-universal-arguments&quot;&gt;Universal arguments&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#frame-and-window-operation&quot; id=&quot;markdown-toc-frame-and-window-operation&quot;&gt;Frame and Window operation&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#frame-management&quot; id=&quot;markdown-toc-frame-management&quot;&gt;Frame management&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#move-by-s-expression&quot; id=&quot;markdown-toc-move-by-s-expression&quot;&gt;Move by S-expression&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#undoredo&quot; id=&quot;markdown-toc-undoredo&quot;&gt;Undo/Redo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#changing-encoding&quot; id=&quot;markdown-toc-changing-encoding&quot;&gt;Changing encoding&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#configuration&quot; id=&quot;markdown-toc-configuration&quot;&gt;Configuration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#loading&quot; id=&quot;markdown-toc-loading&quot;&gt;Loading&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#packagelibraryfeature-names-are-not-managed&quot; id=&quot;markdown-toc-packagelibraryfeature-names-are-not-managed&quot;&gt;Package/Library/Feature names are not Managed&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#buffer-local-variable&quot; id=&quot;markdown-toc-buffer-local-variable&quot;&gt;buffer-local variable&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#elpa&quot; id=&quot;markdown-toc-elpa&quot;&gt;elpa&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#find-init&quot; id=&quot;markdown-toc-find-init&quot;&gt;Find init&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#init-directory&quot; id=&quot;markdown-toc-init-directory&quot;&gt;init directory&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#load-init&quot; id=&quot;markdown-toc-load-init&quot;&gt;Load init&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#initel&quot; id=&quot;markdown-toc-initel&quot;&gt;init.el&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-util&quot; id=&quot;markdown-toc-init-util&quot;&gt;init-util&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-site-lisp&quot; id=&quot;markdown-toc-init-site-lisp&quot;&gt;init-site-lisp&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-elpa&quot; id=&quot;markdown-toc-init-elpa&quot;&gt;init-elpa&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-custom&quot; id=&quot;markdown-toc-init-custom&quot;&gt;init-custom&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-auctex&quot; id=&quot;markdown-toc-init-auctex&quot;&gt;init-auctex&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-elpy&quot; id=&quot;markdown-toc-init-elpy&quot;&gt;init-elpy&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-ido-smex&quot; id=&quot;markdown-toc-init-ido-smex&quot;&gt;init-ido-smex&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-goto-chg&quot; id=&quot;markdown-toc-init-goto-chg&quot;&gt;init-goto-chg&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-undo-tree&quot; id=&quot;markdown-toc-init-undo-tree&quot;&gt;init-undo-tree&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-evil&quot; id=&quot;markdown-toc-init-evil&quot;&gt;init-evil&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-win-nt&quot; id=&quot;markdown-toc-init-win-nt&quot;&gt;init-win-nt&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-chinese-pyim&quot; id=&quot;markdown-toc-init-chinese-pyim&quot;&gt;init-chinese-pyim&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-sdcv&quot; id=&quot;markdown-toc-init-sdcv&quot;&gt;init-sdcv&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#init-yasnippet&quot; id=&quot;markdown-toc-init-yasnippet&quot;&gt;init-yasnippet&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#emacs-243-chinese-characters-on-windows&quot; id=&quot;markdown-toc-emacs-243-chinese-characters-on-windows&quot;&gt;Emacs 24.3 Chinese characters on Windows&lt;/a&gt;    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;#default-pwd-on-windows&quot; id=&quot;markdown-toc-default-pwd-on-windows&quot;&gt;Default PWD on Windows&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#td&quot; id=&quot;markdown-toc-td&quot;&gt;TD&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;readme&quot;&gt;README&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Be patient.&lt;/li&gt;
  &lt;li&gt;Build your own step by step.&lt;/li&gt;
  &lt;li&gt;Long-term maintenance.&lt;/li&gt;
  &lt;li&gt;Read at least the first two chapters of &lt;em&gt;Mastering Emacs&lt;/em&gt; book.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;abcs&quot;&gt;ABCs&lt;/h1&gt;

&lt;p&gt;Read &lt;a href=&quot;http://jimgray.tk/2014/09/14/emacs-installation/&quot;&gt;Emacs installation&lt;/a&gt; first.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Emacs consists of 90% Elisp codes and 10% core C codes. The tiny C part interact with the underlying operating system ABI, while of the Elisp part is the most important - &lt;em&gt;Elisp interpreter&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Almost all of our development and configuration are transferred to the interpreter and finally to the C core.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;All files are buffers, but NOT all buffers are files. Some buffers just a throw-away area to temporarily store snippets from a log file, or manipulate text, or whatever your reason - you just create and name a new buffer.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In Emacs, &lt;em&gt;the buffer is the data structure&lt;/em&gt;. This is an extremely powerful concept because the very same commands you use to move around and edit in Emacs are almost always the same ones you use behind-the-scenes in Elisp.&lt;/p&gt;

    &lt;p&gt;Commands/key bindings/function calls on the front end UI are nearly the same ones in the background Elisp. Hence, when you write Elisp codes to specialize/customize Emacs, you use nearly the same set of commands/functions as you edit a file/buffer.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;It’s important to remember that each buffer can have just one major mode. Minor modes, by contrast, are typically optional add-ons that you enable for some (or all) of your buffers.&lt;/p&gt;

    &lt;p&gt;The major mode is always displayed in the modeline. Some minor modes are also displayed in the modeline, but usually only the ones that alter the buffer or how you interact with it in some way.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;frame-vs-window&quot;&gt;frame VS window&lt;/h1&gt;

&lt;p&gt;Emacs 中两个概念容易混淆，即 frame 和 window。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;frame 就是我们通常所说的“窗口”，譬如，在系统菜单点击 GNU Emacs，那么 Emacs 就会运行，那个整个界面就称为 frame，其实就是 an Emacs process/instance UI，指 Emacs 的整個窗口。&lt;/li&gt;
  &lt;li&gt;window 是 frame 里的小窗口，通常对应一个 buffer。Each frame can have one or more windows, and each window can have exactly one buffer。&lt;/li&gt;
  &lt;li&gt;A &lt;em&gt;window&lt;/em&gt; is just a tiled &lt;em&gt;portion&lt;/em&gt; of the &lt;em&gt;frame&lt;/em&gt;, which is what most modern window managers call a window.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;help-summary&quot;&gt;&lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Help-Summary.html&quot;&gt;Help Summary&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;Emacs is a sophisticated self-documenting editor. Every facet of Emacsis searchable or describable.&lt;/p&gt;

&lt;h3 id=&quot;three-help-utililies&quot;&gt;Three help utililies&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;em&gt;info&lt;/em&gt; Manual&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;M-x:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;info&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;or&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;C-h&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Emacs’s own manuals (and indeed, all manuals in the  ecosystem) are written in TeXinfo. Emacs’s info manual contains more than just topics relating to Emacs. By default, the info browser will index all the other info manuals installed on your system. It even shows info manual of Nano editor which is absolutely not part of Emacs.&lt;/p&gt;

    &lt;p&gt;We usually use &lt;em&gt;info&lt;/em&gt; command in terminal shell. That&apos;s it. The only difference is Emacs has its own TeXinfo viewer. If you want to focus on Emacs manual only without distraction, press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m: Emacs&lt;/code&gt; after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h i&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;This help utility is to get you into a thorough explanation of Emacs things, which is nearly the same as you type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;info&lt;/code&gt; on the command line including the navagation key bindings.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Apropos&lt;/p&gt;

    &lt;p&gt;Emacs has an extensive apropos system that works in much the same way as &lt;em&gt;apropos&lt;/em&gt; does on the command line. The apropos system is especially useful if you’re not entirely sure what you’re looking for or you just know a few characters. There is a variety of niche commands that only search particular aspects of Emacs’s self-documenting internals. And all of apropos supports regular expressions.&lt;/p&gt;

    &lt;p&gt;The most common usage is:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;C-h&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;or&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;M-x:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;apropos-command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;shows all commands (and just the commands, &lt;em&gt;not&lt;/em&gt; functions) that match a given pattern. For example, you are hunting for commands with &quot;coding&quot;, just type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h a&lt;/code&gt; followed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*-coding-*&lt;/code&gt;. There are a wide variaty of &lt;em&gt;apropos&lt;/em&gt; commands to find useful information. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h a apropos&lt;/code&gt; to check the list.&lt;/p&gt;

    &lt;p&gt;If you’re unsure of what you are looking for – maybe you only have part of a name, or you just remember a bit of the documentation – then apropos is a tool that can help you.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The Describe System&lt;/p&gt;

    &lt;p&gt;If you know what you’re looking for, then describe will explain what it is. Every facet of Emacs – be it code written in elisp or the core layer written is C – is accessible and indexed through the describe system. From keys, to commands, character sets, coding systems, fonts, faces, modes, syntax tables and more — it’s all there, neatly categorized.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;To use the three Help Utilities, you always use the prefix key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h&lt;/code&gt; (which is called &lt;em&gt;the help character&lt;/em&gt;) followed by a &lt;em&gt;help option&lt;/em&gt;.&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h f&lt;/code&gt;: help on &lt;em&gt;fuction&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h v&lt;/code&gt;: help on &lt;em&gt;variable&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h m&lt;/code&gt;: help on loaded &lt;em&gt;modes&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h P&lt;/code&gt;: help on &lt;em&gt;packages&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h k&lt;/code&gt;: help on &lt;em&gt;key&lt;/em&gt; bindings.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h t&lt;/code&gt;: builtin basic &lt;em&gt;tutorial&lt;/em&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h w&lt;/code&gt;: check the key bindings of a function.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h c&lt;/code&gt;: check the function of a key binding.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x 8 C-h&lt;/code&gt;: display the list of key bindings starting with&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x 8&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h C&lt;/code&gt;: to see detailed coding system of current buffer. Though the &lt;em&gt;modeline&lt;/em&gt; does give us some hints on &lt;em&gt;coding&lt;/em&gt;, but it is somewhat unclear and obsecure sometimes. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h h&lt;/code&gt; to see what language environment your Emacs supports.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h C-h&lt;/code&gt; to display the list of &lt;em&gt;help options&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;killing-and-deleting&quot;&gt;Killing and Deleting&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Kill VS. Delete&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Killing&lt;/em&gt;: put the killed text in a ring for recovery; usually earase a text blcok.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;Delete&lt;/em&gt;: no ring involved; erase a character or several whitespaces at a time.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-k&lt;/code&gt;  (kill-line) kills all the text from point up to the end of the line.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-Shift-&amp;lt;DEL&amp;gt;&lt;/code&gt; kills tall text from point up to the beginning of the line.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x kill-whole-line&lt;/code&gt; kills the whole line.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x &amp;lt;DEL&amp;gt;&lt;/code&gt; kills back to beginning of sentence. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-k&lt;/code&gt; kills to the end of the sentence.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-w&lt;/code&gt; kill a selected region. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-w&lt;/code&gt; copies the region into the kill ring.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-d&lt;/code&gt; kills the next word. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-&amp;lt;DEL&amp;gt;&lt;/code&gt; kills the previous word.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-d&lt;/code&gt; (the &lt;delect&gt; key) deletes the next character. `&lt;del&gt;` ( the &lt;Backspace&gt; key) deletes the the previous character.&lt;/Backspace&gt;&lt;/del&gt;&lt;/delect&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-a&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-e&lt;/code&gt; moves the beginning and end of &lt;em&gt;sentence&lt;/em&gt;. But Emacs assumes you begin your sentences with &lt;em&gt;two whitespaces&lt;/em&gt; after a period.&lt;/p&gt;

    &lt;p&gt;There is long history of debate over the &lt;em&gt;sentence spacing&lt;/em&gt;. Two whitespaces are mostly used in old days when typewriter was heavily used. While, in modern computer society, &lt;em&gt;proportional/vector fonts&lt;/em&gt; are good at isolating sentences by one space with a period, especially on the WEB.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;useful-keys&quot;&gt;Useful keys&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x h&lt;/code&gt;: select all.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-g&lt;/code&gt;: during execution of Lisp code, this character causes a quit directly. You can use ‘C-g’ to cancel any action you have started.&lt;/p&gt;

    &lt;p&gt;For some actions, you may need to repeat this. (If even this doesn’t clear things up entirely, then try &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-]&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x top-level&lt;/code&gt;; that should do the trick.)&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESC-ESC-ESC&lt;/code&gt;: three consective ESC key. This command can exit an interactive command such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;query-replace (M-%)&lt;/code&gt;,can clear out a prefix argument or a region,can get out of the minibuffer or other recursive edit,cancel the use of the current buffer (for special-purpose buffers),or go back to just one window (by deleting all but the selected window).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-:&lt;/code&gt;: evaluate lisp statement. Alternatively, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x C-e&lt;/code&gt;
over an lisp statement.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x TAB&lt;/code&gt;: Indent all lines starting in the region. If called interactively with no prefix argument, activate a transient mode in which the indentation can be adjusted interactively by typing &lt;left&gt;, &lt;right&gt;, &lt;S-left&gt;, or &lt;S-right&gt;.&lt;/S-right&gt;&lt;/S-left&gt;&lt;/right&gt;&lt;/left&gt;&lt;/p&gt;

    &lt;p&gt;You can prefix it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-u C-x TAB&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-u 6 C-x TAB&lt;/code&gt;. Alternatively, after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x TAB&lt;/code&gt;, use left/right key to move the selected region.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-m&lt;/code&gt;: move point to the first non-whitespace character on this line.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c-q c-l&lt;/code&gt; insert a &lt;em&gt;page break&lt;/em&gt; (also named &lt;em&gt;form feed&lt;/em&gt;, ASCII
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;^L&lt;/code&gt;) character. A page break character is respected by many
printers. Emacs uses it as a logical separation of source
code. To navigate through pages, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x ]&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x [&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;universal-arguments&quot;&gt;Universal arguments&lt;/h1&gt;

&lt;p&gt;Negative arguments add directionality to commands; digits add repetition or change how a command works.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-u a&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-u 4 a&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-u 6 a&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-6 a&lt;/code&gt;; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-u C-u a&lt;/code&gt;; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-u C-u C-u ... a&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-0 a&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-9 a&lt;/code&gt;; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-0 a&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-9 a&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-- 6 a&lt;/code&gt;; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-- 6 a&lt;/code&gt;; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-M-- 6 a&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-- M-d&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-- M-d&lt;/code&gt; both delete the previous word.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But it the former is more convenient as there is no need to switch our finger from Ctrl to Alt. Refer to &lt;em&gt;Universal Arguments&lt;/em&gt; part of &lt;em&gt;Mastering Emacs&lt;/em&gt; book.&lt;/p&gt;

&lt;h1 id=&quot;frame-and-window-operation&quot;&gt;Frame and Window operation&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x 0&lt;/code&gt;: delete &lt;em&gt;active&lt;/em&gt; window; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x o&lt;/code&gt;: switch window.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If other window will be accessed frequently, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x o&lt;/code&gt; is tedious. Emacs support sending commands directly into another window by prefix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x 4&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x 4 C-h&lt;/code&gt; to display the list. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x 4 C-f&lt;/code&gt; will open a file in another window and switch to that window immediately. If we omit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4&lt;/code&gt;, then it will be command opening file in current window.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;frame-management&quot;&gt;Frame management&lt;/h2&gt;

&lt;p&gt;Most of the time, on X system with one monitor, we only open up ONE frame. But what if the monitor big enough and/or two monitors exist?&lt;/p&gt;

&lt;p&gt;Yes, we can make use of more frames at a time. The prefix key used for frames is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x 5&lt;/code&gt;. Like the prefix key for windows, ( &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x 4&lt;/code&gt; ) the commands are mostly the same.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Key Binding&lt;/th&gt;
      &lt;th&gt;Purpose&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;C-x 5 2&lt;/td&gt;
      &lt;td&gt;Create a new frame&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;C-x 5 b&lt;/td&gt;
      &lt;td&gt;Switch buffer in other frame&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;C-x 5 0&lt;/td&gt;
      &lt;td&gt;Delete active frame&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;C-x 5 1&lt;/td&gt;
      &lt;td&gt;Delete other frames&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;C-x 5 C-f&lt;/td&gt;
      &lt;td&gt;Finds a file in the other frame window&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;move-by-s-expression&quot;&gt;Move by S-expression&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;s-expression&lt;/em&gt; (&lt;em&gt;sexp&lt;/em&gt;) can be called &lt;em&gt;balanced expression&lt;/em&gt; especially in programming languages i.e. Python, C, Java etc, typically include:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;Strings&lt;/em&gt;: Programming languages being the primary example of strings, which are balanced expressions because they begin and end with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Brackets&lt;/em&gt;: In most major modes brackets are considered balanced as they have defined open and close characters: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;]&lt;/code&gt; , &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt; , &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;}&lt;/code&gt; , &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Balanced expressions can span multiple lines – multi-line strings for instance – and Emacs knows this.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;key binding&lt;/th&gt;
      &lt;th&gt;purpose&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;C-M-f&lt;/td&gt;
      &lt;td&gt;Move forward by s-expression&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;C-M-b&lt;/td&gt;
      &lt;td&gt;Move backward by s-expression&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;C-M-d&lt;/td&gt;
      &lt;td&gt;Move down into a list&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;C-M-u&lt;/td&gt;
      &lt;td&gt;Move up out of a list&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;C-M-n&lt;/td&gt;
      &lt;td&gt;Move forward to the next list&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;C-M-p&lt;/td&gt;
      &lt;td&gt;Move backward to the previous list&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The first two commands support &lt;em&gt;sexp&lt;/em&gt; fully. The next four work on balanced expressions — but only brackets, and not strings. Emacs those expressions as &apos;list* which means &lt;em&gt;lisp&lt;/em&gt; in the old times. But all cover a wide variaty of coding languages.&lt;/p&gt;

&lt;p&gt;Attention please; these key bindings might not work in Emacs due to Fcitx occupying them.&lt;/p&gt;

&lt;h1 id=&quot;undoredo&quot;&gt;Undo/Redo&lt;/h1&gt;

&lt;p&gt;This section describe the builtin Undo/Redo, NOT the &lt;em&gt;undo-tree&lt;/em&gt; (see configuration below) package.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-/&lt;/code&gt; to undo editing. But how do we &lt;strong&gt;redo&lt;/strong&gt;?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Consecutive repetitions of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-_&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x  u&lt;/code&gt; or  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-/&lt;/code&gt; commands undo earlier and earlier changes, back to the limit of what has been recorded. If all recorded changes have already been undone, the undo command prints an error message and does nothing.&lt;/p&gt;

&lt;p&gt;Any command other than an undo command breaks the sequence of undo commands. Starting  at this moment, the previous undo commands are considered ordinary changes that can  themselves be undone. Thus, you can redo changes you have undone by typing `C-f&apos; or any other command that will have no important effect, and then using more undo commands.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Short explanation&lt;/em&gt;: by undoing the undo. If you undo, and then do a non-editing command such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-f&lt;/code&gt;, then the next undo will undo the undo, resulting in a redo.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;loger explanation&lt;/em&gt;: you can think of undo as operating on a stack of operations. If you perform some command (even a navigation command such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-f&lt;/code&gt;) after a sequence of undo operations, all the undos are pushed on to the operation stack. So the next undo undoes the last command. Suppose you do have an operation sequence that looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Insert &quot;foo&quot;
Insert &quot;bar&quot;
Insert &quot;I love spam&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, you undo. It undoes the last action, resulting in the following list:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Insert &quot;foo&quot;
Insert &quot;bar&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you do something other than undo at this point - say, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-f&lt;/code&gt;, the operation stack looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Insert &quot;foo&quot;
Insert &quot;bar&quot;
Insert &quot;I love spam&quot;
Undo insert &quot;I love spam&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, when you undo, the first thing that is undone is the undo. Resulting in your original stack (and document state):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Insert &quot;foo&quot;
Insert &quot;bar&quot;
Insert &quot;I love spam&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you do a modifying command to break the undo sequence, that command is added after the undo and is thus the first thing to be undone afterwards. Suppose you backspaced over &quot;bar&quot; instead of hitting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-f&lt;/code&gt;. Then you would have had&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Insert &quot;foo&quot;
Insert &quot;bar&quot;
Insert &quot;I love spam&quot;
Undo insert &quot;I love spam&quot;
Delete &quot;bar&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This adding/re-adding happens ad infinitum. It takes a little getting used to, but it really does give Emacs a highly flexible and powerful undo/redo mechanism.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;reference&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.cs.cmu.edu/cgi-bin/info2www?%28emacs%29Undo&quot;&gt;(emacs)Undo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/q/3527142&quot;&gt;How do you &apos;redo&apos; changes after &apos;undo&apos; with Emacs?&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;changing-encoding&quot;&gt;Changing encoding&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;C-x C-m/RET r (M-x: revert-buffer-with-coding-system): if Emacs fails to display file contents.&lt;/li&gt;
  &lt;li&gt;C-x C-m/RET f (M-x: set-buffer-file-coding-system): set file&apos;s encoding when C-x C-s is invoked.&lt;/li&gt;
  &lt;li&gt;C-x C-m/RET c &lt;encoding&gt; C-x C-w (M-x: universal-coding-system-argument): changing file&apos;s encoding immediately by saving as a new file.&lt;/encoding&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;configuration&quot;&gt;Configuration&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;It has been a long time since this post and many updates were made to optimize performance. For latest configuration, refer to the GitHub repository. The configuration Elisp is self-explanatory, full of comments and easy to start off with.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;Everything is synced on GitHub repository.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Plugin/package/library are the same thing to Emacs, all regarded as &lt;em&gt;.el&lt;/em&gt; or &lt;em&gt;.elc&lt;/em&gt; files. These words are used losely, and do NOT have TECHNICAL definitions in Elisp.&lt;/p&gt;

    &lt;p&gt;Emacs 一般称“插件”为 &quot;package&quot; 或者 &quot;library&quot; 。本质上，它们都提供一堆定义好的函数，来实现一些操作，进而实现某个功能。这里多说几句。在 Emacs 中，连移动光标这种最底层的操作都有对应的函数。比如，你在 Emacs 中可以键入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-f&lt;/code&gt; 来将光标向右移动一个字符，同时也可键入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x forward-char&lt;/code&gt; 来实现。任何复杂的功能，比如给文档生成一个目录，都可以被分解为一个个操作，或者说调用一个个函数，而这些函数顺序执行下来功能就得到了实现。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;当 Emacs 想要加载某个插件时，归根到底需要定位并运行一个（也许是一些）脚本文件，那个脚本里定义了实现插件功能所需的变量和函数。Emacs 将它们转变为可供自己使用的对象（Elisp object），放到运行环境中等待调用。而脚本自身还可以在内部进一步加载其他脚本。&lt;/li&gt;
  &lt;li&gt;When editing &lt;em&gt;init&lt;/em&gt; files manually, pay attention the &lt;em&gt;lisp&lt;/em&gt; grammar. They can also be modified by &lt;em&gt;M-x: customize variable&lt;/em&gt; GUI.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If Emacs is running as &lt;em&gt;daemon&lt;/em&gt; server mode, updates to &lt;em&gt;init&lt;/em&gt; files does &lt;strong&gt;Not&lt;/strong&gt; take effect until &lt;em&gt;daemon&lt;/em&gt; server is re-launched!&lt;/p&gt;

    &lt;p&gt;So when configuring Emacs, use &lt;em&gt;emacs&lt;/em&gt; instead of C/S mode &lt;em&gt;emacsclient&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;Common Lisp&lt;/em&gt; requires a slash ending of directory name while &lt;em&gt;Emacs Lisp&lt;/em&gt; does not.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/purcell/emacs.d&quot;&gt;purcell&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/redguardtoo/mastering-emacs-in-one-year-guide&quot;&gt;master emacs in one year&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.zybuluo.com/qqiseeu/note/17692&quot;&gt;Emacs配置文件——新手攻略&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;loading&quot;&gt;Loading&lt;/h1&gt;

&lt;p&gt;其实，连整个 Emacs 的启动都可以概括为一句话：加载一系列脚本。只不过这些脚本有的是内置的（built in），有的是你安装的插件包含的，有的是你自己写的。配置emacs归根结底是在配置各种各样的脚本。&lt;/p&gt;

&lt;p&gt;Emacs Lisp&apos;s Library System: What&apos;s &lt;em&gt;require&lt;/em&gt;, &lt;em&gt;load&lt;/em&gt;, &lt;em&gt;load-library&lt;/em&gt;, &lt;em&gt;load-file&lt;/em&gt;, &lt;em&gt;autoload&lt;/em&gt;, &lt;em&gt;feature&lt;/em&gt;?&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Interactive lisp function.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h f interactive&lt;/code&gt;: specify a way of parsing arguments for interactive use of a function. &lt;em&gt;interactive&lt;/em&gt; can be invoked by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x:&lt;/code&gt; and prompts user to input arguments on-the-fly. It declares that the function in which it appears is a &lt;em&gt;command&lt;/em&gt;, and that it may therefore be called interactively (via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x&lt;/code&gt; or by entering a key sequence bound to it).&lt;/p&gt;

    &lt;p&gt;Most of time, they are bound to shortcut keys, which is optional.  Without &lt;em&gt;interactive&lt;/em&gt;, a function can only be called &lt;em&gt;programmatically&lt;/em&gt; (in Elisp &lt;em&gt;.el&lt;/em&gt; sources), not from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x&lt;/code&gt; nor via key-binding.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;interactive&lt;/em&gt; functions are functions and therefore not constrained to mini-buffer. Instead, they can be called &lt;em&gt;programmatically&lt;/em&gt; by supplying a default &lt;em&gt;interactive&lt;/em&gt; argument (if really need) in Elisp sources.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;load-file&lt;/em&gt; - interactive&lt;/p&gt;

    &lt;p&gt;Load one specific file by &lt;em&gt;full file path&lt;/em&gt;. “.el” or “.elc” file name extentions are not auto added, but “.gz” is. Use this when you don&apos;t want emacs to guess the file name extention of “.el”, “.elc” or none.&lt;/p&gt;

    &lt;p&gt;So basically the file can be put anywhere as long as you remember the file path.&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;M-x:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-file&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;~/elisp/foo-bar.el&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;or&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-file&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;~/elisp/foo-bar.el&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;&lt;em&gt;load-file&lt;/em&gt; is not a smart way to pull in libraries as you have to remember and offer each library full path on call.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;load&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;Usually it is better to install files in your &lt;em&gt;load-path&lt;/em&gt;, though. Load a file by searching through directories of &lt;em&gt;load-path&lt;/em&gt;. Argument should be just the file name without full path.&lt;/p&gt;

    &lt;p&gt;If file extension is omitted, it will auto add &lt;em&gt;.elc&lt;/em&gt; for compiled version if exist, or add &lt;em&gt;.el&lt;/em&gt;, or with &lt;em&gt;.gz&lt;/em&gt;. Preference is given to the &lt;em&gt;compiled&lt;/em&gt; (&lt;em&gt;.elc&lt;/em&gt;) version.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;load-libarry&lt;/em&gt; - interactive&lt;/p&gt;

    &lt;p&gt;It is the &lt;em&gt;interactive&lt;/em&gt; version of &lt;em&gt;load&lt;/em&gt;. Can be called by	&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x&lt;/code&gt; (or key bindings if exists) to read arguments.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;require&lt;/em&gt;&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;foo-bar&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;the-library-file&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;&amp;lt;soft-flag&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;A library declares that it provides a certain &lt;em&gt;foo-bar&lt;/em&gt; feature as follows:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;provide&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;foo-bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Checks the variable &lt;em&gt;features&lt;/em&gt;, if symbol &lt;em&gt;foo-bar&lt;/em&gt; is not a member of that list, &lt;em&gt;foo-bar&lt;/em&gt; is not loaded yet. If &lt;em&gt;foo-bar&lt;/em&gt; is not loaded, load it from &lt;em&gt;the-library-file&lt;/em&gt; (which defined the &lt;em&gt;foo-bar&lt;/em&gt; feature).&lt;/p&gt;

    &lt;p&gt;If &lt;em&gt;the-library-file&lt;/em&gt; is omitted, the printname of &lt;em&gt;foo-bar&lt;/em&gt; is used as the file name, and &lt;em&gt;load&lt;/em&gt; will try to load this name appended with the suffix &lt;em&gt;.elc&lt;/em&gt; or &lt;em&gt;.el&lt;/em&gt;, in that order. &lt;em&gt;the-library-file&lt;/em&gt; (file name) is guessed from the feature name - &lt;em&gt;foo-bar&lt;/em&gt; in this case.&lt;/p&gt;

    &lt;p&gt;Load a package if it has not already been loaded. It won&apos;t load a library twice. It is similar to other lang&apos;s “require” or “import”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;autoload&lt;/em&gt;&lt;/p&gt;

    &lt;p&gt;Load a file only when a function is called - on-demand loading. Associate a function name with a file path. When the function is called, load the file, and execute the function.&lt;/p&gt;

    &lt;p&gt;The &lt;em&gt;autoload&lt;/em&gt; facility lets you register the existence of a function or macro, but put off loading the file that defines it. The first call to the function automatically loads the proper library, in order to install the real definition and other associated code, then runs the real definition as if it had been loaded all along. Autoloading can also be triggered by looking up the documentation of the function or macro.&lt;/p&gt;

    &lt;p&gt;这样做的一个好处是，避免在启动 Emacs 时因为执行过多代码而效率低下，比如启动慢，卡系统等。想象一下，如果你安装了大量的有关 Python 开发的插件，而某次打开 Emacs 只是希望写点日记，你肯定不希望这些插件在启动时就被加载，让你白白等上几秒，也不希望这些插件在你做文本编辑时抢占系统资源（内存，CPU 时间等）。所以，一个合理的配置应该是，当你打开某个 Python 脚本，或者手动进入 Python 的编辑模式时，才加载那些插件。&lt;/p&gt;

    &lt;p&gt;Loading a file triggered by calling a function defined is in it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;All the loading facilities at the end call the &lt;em&gt;load&lt;/em&gt; function to do their job. Refer to &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_node/elisp/How-Programs-Do-Loading.html&quot;&gt;how programs do loading &lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;packagelibraryfeature-names-are-not-managed&quot;&gt;Package/Library/Feature names are not Managed&lt;/h1&gt;

&lt;p&gt;There is no absolute relation between any concept of package/library/feature/autoload facilities and the file name. If there exists relation, it&apos;s just a programming convention.&lt;/p&gt;

&lt;p&gt;By convention, if a elisp file name is &lt;em&gt;xyz-mode.el&lt;/em&gt;, it OFTEN provides a lisp symbol &lt;em&gt;xyz-mode&lt;/em&gt; as its feature name (if it does at all), and the command to invoke the mode is OFTEN named &lt;em&gt;xyz-mode&lt;/em&gt;. Sometimes the &lt;em&gt;-mode&lt;/em&gt; part is omitted in any of {file name, feature symbol name, command name}.&lt;/p&gt;

&lt;p&gt;This is only a lose convention. There are a lot exceptions. For example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The file &lt;em&gt;lisp-mode.el&lt;/em&gt; provides the symbol &lt;em&gt;lisp-mode&lt;/em&gt; as feature, and is invoked by a command named &lt;em&gt;emacs-lisp-mode&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;cua-base.el&lt;/em&gt; file provides symbols &lt;em&gt;cua-base&lt;/em&gt; and &lt;em&gt;cua&lt;/em&gt; as features, and is invoked by a command named &lt;em&gt;cua-mode&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;em&gt;text-mode.el&lt;/em&gt; file does not provide any symbol for feature. It is invoked by a command named &lt;em&gt;text-mode&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;The file &lt;em&gt;desktop.el&lt;/em&gt; provides the symbol &lt;em&gt;desktop&lt;/em&gt; as feature, and the command name to invoke it is &lt;em&gt;desktop-save-mode&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the above means, you could have a file named &lt;em&gt;Joe-xyz-mode_v2.1.el&lt;/em&gt;, which provides a feature named &lt;em&gt;abc&lt;/em&gt;, while the command name to activate it may be &lt;em&gt;opq&lt;/em&gt;, and it might be displayed in mode line as &lt;em&gt;OPQ helper&lt;/em&gt;. And, this file can be considered as a &lt;em&gt;package&lt;/em&gt; or &lt;em&gt;library&lt;/em&gt;.&lt;/p&gt;

&lt;h1 id=&quot;buffer-local-variable&quot;&gt;buffer-local variable&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;If a variable is &lt;em&gt;buffer-local&lt;/em&gt;, means the value is specific to that current buffer (where the cursor blinks). Different buffers might have different values. &lt;em&gt;default-directory&lt;/em&gt; and &lt;em&gt;tab-width&lt;/em&gt; are such variables.&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setq&lt;/code&gt; to change current value, which will overrides global default value. For example, on Linux, Emacs&apos;s global default &lt;em&gt;default-directory&lt;/em&gt; is &lt;em&gt;~/&lt;/em&gt; for all buffers. After evaluating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(setq default-directory &quot;~/workspace/&quot;)&lt;/code&gt;, the &lt;em&gt;default-directory&lt;/em&gt; of current buffer is changed to &lt;em&gt;~/workspace/&lt;/em&gt;, while other buffers&apos; (without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setq&lt;/code&gt;) &lt;em&gt;default-directory&lt;/em&gt; remains to be global default &lt;em&gt;~/&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Usually in Emacs &lt;em&gt;init.el&lt;/em&gt;, we can change the global default &lt;em&gt;default-directory&lt;/em&gt; by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(setq-default default-directory &quot;/path/&quot;)&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(setq default-directory &quot;/path/&quot;)&lt;/code&gt; in &lt;em&gt;init.el&lt;/em&gt; only change the very first buffer&apos;s &lt;em&gt;default-directory&lt;/em&gt; on startup.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;elpa&quot;&gt;elpa&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Compared to install libraries manually, &lt;em&gt;elpa&lt;/em&gt; automates the process.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x: list-packages&lt;/code&gt;，会启动 Emacs 自带的插件管理器 elpa (Emacs lisp package archive)。例如找到 auctex，按下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; 标记为安装，再按 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; 开始安装。除了 Emacs 官方的 elpa，还有添加 melpa，org 等 package archives。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Library is only loaded after init files are parsed. So when modifying a &lt;em&gt;variable&lt;/em&gt; defined in that library during init files parsing, require/load it first!&lt;/p&gt;

    &lt;p&gt;Take &lt;em&gt;elpa&lt;/em&gt; itself for example, if we would like to add a package archive i.e. &lt;em&gt;melpa&lt;/em&gt;, we should first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(require &apos;package)&lt;/code&gt;, then update the variable &lt;em&gt;package-archive&lt;/em&gt; defined within &lt;em&gt;package.el&lt;/em&gt;. In &lt;em&gt;init-elpa.el&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;package-enable-at-startup&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;are appended after that. The first line is to disable load of installed packages after all init files. The 2nd line is to load those packages. That is to load installed packages earlier as usual.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;find-init&quot;&gt;Find init&lt;/h1&gt;

&lt;p&gt;Normally Emacs uses the environment variable HOME to find .emacs; that’s what ‘~’ means in a file name. If .emacs is not found inside ~/ (nor .emacs.el), Emacs looks for ~/.emacs.d/init.el (which, like ~/.emacs.el, can be byte-compiled).&lt;/p&gt;

&lt;p&gt;However, if you run Emacs from a shell started by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;su&lt;/code&gt;, Emacs tries to find your own .emacs, not that of the user you are currently pretending to be. The idea is that you should get your own editor customizations even if you are running/pretending as the super user. If use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;su -&lt;/code&gt;, then you are not pretending but indeed that user.&lt;/p&gt;

&lt;p&gt;More precisely, Emacs first determines which user’s init file to use. It gets your user name from the environment variables LOGNAME and USER; if neither of those exists, it uses effective user-ID. If that user name matches the real user-ID, then Emacs uses HOME; otherwise, it looks up the home directory corresponding to that user name in the system’s data base of users.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;After startup, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h v user-init-file&lt;/code&gt; to see your init file location.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If during configuration, you modified and want to verify init files:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;M-x:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-file&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;M-x:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-library&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;To load &lt;em&gt;HOME/.emacs.d/init.el&lt;/em&gt;. If current buffer is your init file config, use:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;M-x:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;eval-buffer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;You can usually just re-evaluate the changed region. Mark the region of ~/.emacs that you&apos;ve changed, and then use:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;M-x:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;eval-region&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Simple code can be evaluated in minibuffer as well:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;M-:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;list-code-here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;More read on &lt;a href=&quot;http://stackoverflow.com/q/2580650&quot;&gt;How can I reload .emacs after changing it?&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;init-directory&quot;&gt;init directory&lt;/h2&gt;

&lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ tree -a -C -F -L 2 -I *~ .emacs.d/&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.emacs.d/
├── .git/                   # git directory
│   ├── COMMIT_EDITMSG
│   ├── HEAD
│   ├── config
│   ├── description
│   ├── hooks/
│   ├── index
│   ├── info/
│   ├── logs/
│   ├── objects/
│   ├── packed-refs
│   └── refs/
├── .gitignore
├── LICENSE.md
├── README.md
├── auto-save-list/
├── elpa/                   # pkg installed through builtin package manager
│   ├── archives/
│   ├── auctex-11.88.9/
│   ├── auctex-11.88.9.signed
│   ├── company-0.8.12/
│   ├── elpy-1.10.0/
│   ├── evil-readme.txt
│   ├── find-file-in-project-3.8/
│   ├── flx-0.6.1/
│   ├── flx-ido-0.6.1/
│   ├── flx-ido-readme.txt
│   ├── fullframe-0.1.1/
│   ├── gnupg/
│   ├── goto-last-change-readme.txt
│   ├── highlight-indentation-0.7.0/
│   ├── ido-completing-read+-3.7/
│   ├── ido-ubiquitous-3.7/
│   ├── pyvenv-1.9/
│   ├── smex-3.0/
│   ├── swiper-0.6.0/
│   ├── undo-tree-0.6.5/
│   ├── undo-tree-0.6.5.signed
│   ├── undo-tree-readme.txt
│   ├── yasnippet-0.9.0.1/
│   └── yasnippet-readme.txt
├── init.el                 # first init file loaded
├── lisp/                   # specific pkg&apos;s init file
│   ├── init-auctex.el
│   ├── init-custom.el
│   ├── init-elpa.el
│   ├── init-elpy.el
│   ├── init-evil.el
│   ├── init-goto-chg.el
│   ├── init-ido.el
│   ├── init-site-lisp.el
│   ├── init-undo-tree.el
│   ├── init-utils.el
│   └── init-win-nt.el
└── site-lisp/              # manually installed pkgs located here.
    ├── evil/
    └── goto-chg/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;load-init&quot;&gt;Load init&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;When Emacs starts, it first load &lt;em&gt;init.el&lt;/em&gt; which in turn load package-specific &lt;em&gt;init-file-name.el&lt;/em&gt; configs under &lt;em&gt;lisp/&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;All &lt;em&gt;init-file-name.el&lt;/em&gt; files MUST end up with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(provide &lt;/code&gt;init-file-name)` (file name without &lt;em&gt;.el&lt;/em&gt; extension).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;site-lisp/&lt;/em&gt; is where manually installed packages located, i.e. &lt;em&gt;goto-chg&lt;/em&gt; and &lt;em&gt;evil&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;elpa/&lt;/em&gt; stores packages installed through Emacs builtin package manager &lt;em&gt;package.el&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;package.el&lt;/em&gt; itself is also a Emacs library/package. It specially manages other packages.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Each time a package is installed:
    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;Usually add an &lt;em&gt;init-pkg-name.el&lt;/em&gt; config file under &lt;em&gt;lisp/&lt;/em&gt;. This file is specific to that installed package only.&lt;/p&gt;

        &lt;p&gt;If this package is manually installed, then the config file needs more lisp codes to adjust performance. However, if it installed by builtin package managers, most configs are done in &lt;em&gt;elpa/pkg-name-version/&lt;/em&gt;. Just a few arguments is enough.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(require &apos;init-pkg-name)&lt;/code&gt; in &lt;em&gt;init.el&lt;/em&gt;.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;initel&quot;&gt;init.el&lt;/h2&gt;

&lt;p&gt;The very first feature loaded on startup.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;; Check Emacs version.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;minver&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;23.3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;version&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;emacs-version&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;23.1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Your Emacs is too old -- this config requires v%s or higher&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;minver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;version&amp;lt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;emacs-version&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;24&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Your Emacs is old, and some functionality in this config will be disabled. Please upgrade if possible.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Init lisp el load path. Common lisp needs the end slash.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; People with a CommonLisp background like to make sure that&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; the entry ends with a trailing slash, but this is not required by EmacsLisp.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;load-path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;lisp&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user-emacs-directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Temporarily reduce garbage collection during startup&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;defconst&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sanityinc/initial-gc-cons-threshold&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;gc-cons-threshold&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Initial value of `gc-cons-threshold&apos; at start-up time.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;gc-cons-threshold&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;after-init-hook&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;gc-cons-threshold&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sanityinc/initial-gc-cons-threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Load init lisp el. Each required feature corresponds to&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; a feature file - feature.el under ~/.emacs.d/lisp/ directory.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-site-lisp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;;;Must come before init-elpa, as it may provide package.el&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-elpa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-custom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-auctex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-elpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-ido&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-goto-chg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-undo-tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-evil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-win-nt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;provide&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;init&lt;/em&gt; itself is also a feature. End with&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;provide&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;to provide feature. A feature must be &lt;em&gt;provide&lt;/em&gt;d before &lt;em&gt;require&lt;/em&gt;d.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Check Emacs version and give warning/error if too old.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;user-emacs-directory&lt;/em&gt; refers to &lt;em&gt;~/.emacs.d/&lt;/em&gt; where &apos;~&apos; is determined by user environment variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HOME&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-h v user-emacs-directory&lt;/code&gt; shows the exact path.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Reduce garbage collection on startup from &lt;a href=&quot;https://github.com/purcell/emacs.d&quot;&gt;purcell&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Pay attention to &lt;em&gt;require&lt;/em&gt; orders, i.e. &lt;em&gt;init-site-lisp&lt;/em&gt; comes before &lt;em&gt;init-elpa&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;init-util&quot;&gt;init-util&lt;/h2&gt;

&lt;p&gt;This feature is copied from &lt;a href=&quot;https://github.com/purcell/emacs.d&quot;&gt;purcell&lt;/a&gt;. There are many functions and a special macro - &lt;em&gt;after-load&lt;/em&gt; (alias as &lt;em&gt;with-eval-after-load&lt;/em&gt;). Self-defined functions/macros are only useful when you are familiar with and really nee them.&lt;/p&gt;

&lt;p&gt;Feature &lt;em&gt;site-lisp&lt;/em&gt; need &lt;em&gt;after-load&lt;/em&gt; macro support.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;fboundp&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;with-eval-after-load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;defalias&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;after-load&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;with-eval-after-load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defmacro&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;after-load&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;feature&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;amp;rest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;After FEATURE is loaded, evaluate BODY.&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;indent&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;eval-after-load&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;feature&lt;/span&gt;
       &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;progn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;init-site-lisp&quot;&gt;init-site-lisp&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;site-lisp&lt;/em&gt; mainly achieve two items:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Add each subdirectory of &lt;em&gt;site-lisp&lt;/em&gt; to &lt;em&gt;load-path&lt;/em&gt;.&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;remove&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;site-lisp/test/&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user-emacs-directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;nb&quot;&gt;or&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;load-path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;lisp&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user-emacs-directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;These two statements both operates on a single directory.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If Emacs version &amp;lt;= 23, download a package manager &lt;em&gt;package.el&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;; Add each subdirectory at different levels of site-lisp to the beginning&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; of load-path,including site-lisp itself. To remove site-lisp itself,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; remove:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;  (append&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;   (copy-sequence (normal-top-level-add-to-load-path &apos;(&quot;.&quot;)))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; To remove a subdir of site-lisp from load-path:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;  (setq load-path (remove (expand-file-name &quot;site-lisp/test/&quot; user-emacs-directory) load-path)))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; For example, site-lisp/package is removed if Emacs version &amp;gt; 23.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; site-lisp/evil/lib is removed from load-path as well.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; Adding to the end of load-path is much easier, pleae refer to&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;   http://www.emacswiki.org/emacs/LoadPath.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; lisp and site-lisp are both in load-path but serve different roles.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; lisp is to configure package behaviour while manually installed packages&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; are located in site-lips.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; It will add subdirs at different levels to load-path.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;default-directory&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;expand-file-name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;site-lisp&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;user-emacs-directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-path&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;append&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;copy-sequence&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;load-path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;;; Shadow&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;append&lt;/span&gt; 
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;copy-sequence&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;normal-top-level-add-to-load-path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;normal-top-level-add-subdirs-to-load-path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;load-path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;init-elpa&quot;&gt;init-elpa&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Add several package repositories to &lt;em&gt;package manager&lt;/em&gt; - package.el&lt;/p&gt;

    &lt;p&gt;&lt;em&gt;org&lt;/em&gt; and &lt;em&gt;melpa stable&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;On demand installation of packages.&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;require-package&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;package-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;package-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;With this code in your config, self-defined function &lt;em&gt;require-package&lt;/em&gt; will download and load &lt;em&gt;package-name&lt;/em&gt; automatically!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;init-custom&quot;&gt;init-custom&lt;/h2&gt;

&lt;p&gt;Mainly personal like to adjust the basics of Emacs.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; Configs that change the basics of Emacs are put here.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Enable line number mode on startup.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global-linum-mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Display colum number at mode line.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;column-number-mode&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;;; Language - UTF-8&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Disable CJK encoding&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;utf-translate-cjk-mode&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;;; Set UTF-8 language environment. Don&apos;t use &apos;UTF-8 or&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; &apos;utf-8! LANGUAGE-NAME should be a string - the name&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; of a language environment.  For example, &quot;Latin-1&quot;.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set-language-environment&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set-default-coding-systems&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;utf-8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set-terminal-coding-system&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;utf-8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set-keyboard-coding-system&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;utf-8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;locale-coding-system&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;utf-8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set-selection-coding-system&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;utf-8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;setq-default&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;buffer-file-coding-system&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;utf-8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; priority based on reverse order, so the last one is used first&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prefer-coding-system&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;utf-8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;provide&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-custom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;reference&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://masutaka.net/chalow/2009-07-09-1.html&quot;&gt;2009-07-09&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.csdn.net/sanwu2010/article/details/23994977&quot;&gt;windows下Emacs中文乱码解决办法&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;init-auctex&quot;&gt;init-auctex&lt;/h2&gt;

&lt;p&gt;Please refer to &lt;a href=&quot;http://jimgray.tk/2015/01/30/auctex-emacs/&quot;&gt;auctex emacs&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;init-elpy&quot;&gt;init-elpy&lt;/h2&gt;

&lt;p&gt;Emacs Python Development Environment.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;; lisp/init-elpy.el&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;elpy-enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;provide&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-elpy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;elpy&lt;/em&gt; requires &lt;em&gt;pyvenv&lt;/em&gt; - python virtualenv support which is a global minor mode.&lt;/p&gt;

    &lt;p&gt;So when programming, Emacs is aware of and can activate/deactivate virutalenv! By default, &lt;em&gt;pyvenv&lt;/em&gt; mode is turned globally on Emacs startup.&lt;/p&gt;

    &lt;p&gt;Mainly through command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x: pyvenv-activate&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x: pyvenv-deactivate&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In order to support &lt;em&gt;elpy&lt;/em&gt; better, we need to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install&lt;/code&gt; several backends like &lt;em&gt;rope&lt;/em&gt;, &lt;em&gt;jedi&lt;/em&gt;, &lt;em&gt;flake8&lt;/em&gt;, &lt;em&gt;importmagic&lt;/em&gt;, &lt;em&gt;autopep8&lt;/em&gt; in &lt;em&gt;virtualenv&lt;/em&gt;.&lt;/p&gt;

    &lt;p&gt;Install these Python packages in &lt;em&gt;virtualenv&lt;/em&gt; instead of in global environment. Do NOT mess true system up.&lt;/p&gt;

    &lt;p&gt;Details refer to &lt;a href=&quot;http://www.jimgray.tk/2015/03/05/python-virtualenv/&quot;&gt;python virtualenv&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;When programing with Python, first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x: pyvenv-activate&lt;/code&gt; to enable virtualenv in Emacs.&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x: elpy-config&lt;/code&gt; to check elpy configs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reference:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/jorgenschaefer/elpy&quot;&gt;elpy github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://elpy.readthedocs.org/en/latest/index.html&quot;&gt;readdoc elpy&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;init-ido-smex&quot;&gt;init-ido-smex&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.emacswiki.org/emacs/InteractivelyDoThings&quot;&gt;IDO&lt;/a&gt; lets you interactively do things with buffers and files.&lt;/p&gt;

&lt;p&gt;Emacs now has a builtin &lt;em&gt;ido.el&lt;/em&gt; which just focuses on files and buffers. However &lt;em&gt;ido-ubiquitous.el&lt;/em&gt; enable ido-style completion everywhere for almost every function that uses the standard completion function.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;First enable builtin &lt;em&gt;ido&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; Enable ido in as many places as possible&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ido-mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ido-everywhere&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable &lt;em&gt;ido-ubiquitous&lt;/em&gt;:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;; (require &apos;ido-ubiquitous)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ido-ubiquitous-mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;init-goto-chg&quot;&gt;init-goto-chg&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;evil&lt;/em&gt; depends on &lt;em&gt;goto-chg&lt;/em&gt; which is not in stable &lt;em&gt;melpa&lt;/em&gt; repository. So install both &lt;em&gt;evil&lt;/em&gt; and &lt;em&gt;goto-chg&lt;/em&gt; manually. Download and put &lt;em&gt;goto-chg.el&lt;/em&gt; to &lt;em&gt;site-lisp/goto-chg/&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; Goto the point of the most recent edit in the buffer.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;; When repeated, goto the second most recent edit, etc.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;; Negative argument, C-u -, for reverse direction.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;; Works by looking into buffer-undo-list to find points of edit.&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;goto-chg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Define key bindings. Otherwise M-x: goto-last-change[-reverse]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; each time.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global-set-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;control&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;goto-last-change&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global-set-key&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;control&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;?,&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;goto-last-change-reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;provide&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-goto-chg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Two &lt;em&gt;global&lt;/em&gt; key bindings (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-.&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-,&lt;/code&gt;) are defined for &lt;em&gt;goto-chg&lt;/em&gt;. These two key bindings work everywhere no matter what modes are Emacs in. &lt;em&gt;evil&lt;/em&gt; itself also define two key bindings (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g-;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;g-,&lt;/code&gt;) only work within &lt;em&gt;evil&lt;/em&gt; mode.&lt;/p&gt;

&lt;h2 id=&quot;init-undo-tree&quot;&gt;init-undo-tree&lt;/h2&gt;

&lt;p&gt;Emacs&apos;s builtin undo/redo (see above &lt;em&gt;Undo/Redo&lt;/em&gt; section) is confusing and not intuitive to use. This package is to replace Emacs&apos; undo system with a system that treats undo history as what it is: a branching tree of changes. This simple idea allows the more intuitive behaviour of the standard undo/redo system to be combined with the power of never losing any history.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; Replace Emacs built-in undo/redo with undo-tree.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; Turn on undo-tree globally everywhere.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global-undo-tree-mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;provide&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-undo-tree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;init-evil&quot;&gt;init-evil&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;evil&lt;/em&gt; is not in stable &lt;em&gt;melpa&lt;/em&gt; repository. So I install it manually.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.emacswiki.org/emacs/Evil&quot;&gt;Emacs Evil&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Download and extract evil source to &lt;em&gt;site-lisp/evil/&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; Load evil mode&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;;; evil requires undo-tree and goto-chg which must be&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;;; loaded at first.&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;;; evil was installed manually, so require it first before enabling it.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;evil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;evil-mode&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;By setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(evil-mode 1)&lt;/code&gt;, Emacs enters evil mode by default. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-z&lt;/code&gt; to switch between evil and normal Emacs.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;init-win-nt&quot;&gt;init-win-nt&lt;/h2&gt;

&lt;p&gt;Mainly special options for Windows system.&lt;/p&gt;

&lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;;;; Windows system specific configs.&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;system-type&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;windows-nt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;progn&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;;; Set default directory.&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;default-directory&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;E:/workspace&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;;; Set Chinese fonts, otherwise mojibak in a mess.&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;set-fontset-font&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fontset-default&quot;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;gb18030&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Microsoft YaHei&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;unicode-bmp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;provide&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;init-win-nt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are many other Windows configs, but integrated into other features, like AucTeX PDF viewer in &lt;em&gt;init-auctex&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;init-chinese-pyim&quot;&gt;init-chinese-pyim&lt;/h2&gt;

&lt;p&gt;中文输入法，可以在 console/terminal 下使用。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Install through &lt;em&gt;melpa&lt;/em&gt; repository.&lt;/p&gt;

    &lt;p&gt;In &lt;em&gt;*scratch*&lt;/em&gt; buffer input:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&apos;package-archives&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;melpa&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://melpa.org/packages/&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Temporarily enable &lt;em&gt;melpa&lt;/em&gt; repository.&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;M-:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;eval-buffer&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;M-x:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;list-packages&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Find &lt;em&gt;chinese-pyim&lt;/em&gt; and install it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Configure&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(setq pyim-dicts
  ; 主词库
  &apos;((:name &quot;bigdict&quot;
     :file #(&quot;/home/zachary/.emacs.d/pyim/dicts/pyim-bigdict.pyim&quot; 14 23
         (face flx-highlight-face)
         23 25
         (face flx-highlight-face))
     :coding utf-8-unix
     :dict-type pinyin-dict)
    ; guesss dict 两个联想词库
    (:name &quot;guessdict-a&quot;
     :file &quot;/home/zachary/.emacs.d/pyim/dicts/pyim-guessdict-a.gpyim&quot;
     :coding utf-8-unix
     :dict-type guess-dict)
    (:name &quot;guessdict-b&quot;
     :file &quot;/home/zachary/.emacs.d/pyim/dicts/pyim-guessdict-b.gpyim&quot;
     :coding utf-8-unix
     :dict-type guess-dict)))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;里面的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;14 23 (face flx-highlight-face)&lt;/code&gt; 好像可以去掉，不知道是不是因为我的 Emacs 里其它插件自动调整的。&lt;/p&gt;

    &lt;p&gt;It&apos;s important to configure a good phrase file (词库）. &lt;em&gt;chinese-pyim&lt;/em&gt; phrase file &lt;em&gt;.pyim&lt;/em&gt; is much the same as &lt;em&gt;.org&lt;/em&gt; format except that it uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt;. Both &lt;em&gt;org&lt;/em&gt; and &lt;em&gt;pyim&lt;/em&gt; are normal text file. More on &lt;em&gt;org&lt;/em&gt; phrase file, refer to &lt;a href=&quot;/2016/01/01/ime/&quot;&gt;Fcitx&lt;/a&gt; post. By &lt;em&gt;org&lt;/em&gt; phrase file, we can generate both phrase file for &lt;em&gt;fcitx .mb&lt;/em&gt; and &lt;em&gt;chinese-pyim .pyim&lt;/em&gt; format. But pay attention to their difference.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Refer to &lt;a href=&quot;https://github.com/tumashu/chinese-pyim&quot;&gt;github chinese-pyim&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;init-sdcv&quot;&gt;init-sdcv&lt;/h2&gt;

&lt;p&gt;A console version of &lt;em&gt;StarDict&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;init-yasnippet&quot;&gt;init-yasnippet&lt;/h2&gt;

&lt;p&gt;这个插件可以让你用 TAB 键自动补齐代码。&lt;/p&gt;

&lt;h1 id=&quot;emacs-243-chinese-characters-on-windows&quot;&gt;Emacs 24.3 Chinese characters on Windows&lt;/h1&gt;

&lt;p&gt;系统为英文版 Windows RTM X64。在使用 Emacs 24.3 打开文件时候，发现中文字体部分显示为方块。通过对编码的设置依然不能解决问题。在网上查找解决方案的时候，发现有人提到通过设置字体能够解决这个问题。于是仔细看了下 Emacs 里的那些个方块，里面的内容其实是中文的编码，由于不能显示对应的文字，Emacs 于是原样将字符编码给打印出来。能够显示的中文也很丑，歪歪扭扭。进入控制面板里查看了下字体，发现中文该有的字体都有，只是不同的是，英文版下字体自然也是英文名称。于是根据谷歌的搜索，在 init 文件的最开始写入如下内容：&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(set-fontset-font &quot;fontset-default&quot; &apos;gb18030&apos; (&quot;Microsoft YaHei&quot; . &quot;unicode-bmp&quot;))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;reference&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.csdn.net/qianchenglenger/article/details/10950769&quot;&gt;Emacs在win8乱码&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;default-pwd-on-windows&quot;&gt;Default PWD on Windows&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PWD&lt;/code&gt; denotes &lt;em&gt;print name of current/working directory&lt;/em&gt;. When starting Emacs through Windows shortcut, and using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-x C-f&lt;/code&gt; to open a file, you find that the default directory is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C\windows\system32&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To change the default directory by either of the two:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Either edit the Emacs shortcut, in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start in&lt;/code&gt; field, fill in your default working directory.&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Or add:&lt;/p&gt;

    &lt;div class=&quot;language-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;default-directory&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;E:/workspace&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;td&quot;&gt;TD&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;require vs autoload vs load[-libarry]&lt;/li&gt;
  &lt;li&gt;elpa packages activate/load default? package-activated-list, so many packages activated, but need only some of them.&lt;/li&gt;
  &lt;li&gt;set default fonts?&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.jianshu.com/p/99c3f6fa6355&quot;&gt;emacs 配置整理&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.jianshu.com/p/b4cf683c25f3&quot;&gt;从零开始——Emacs 安装配置使用教程 2015&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://ergoemacs.org/emacs/elisp_library_system.html&quot;&gt;elisp library system&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;https://github.com/purcell/emacs.d, https://github.com/bbatsov/prelude&lt;/li&gt;
  &lt;li&gt;eshell?&lt;/li&gt;
  &lt;li&gt;Caps Lock VS Ctrl?&lt;/li&gt;
  &lt;li&gt;use package to speed up&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>中国历史经典</title>
   <link href="/2014/06/10/cn-history-proverb/"/>
   <updated>2014-06-10T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/06/10/cn-history-proverb</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;摘自网络，非原创。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;1、天下之事，分合交替，分久必合，合久必分：&lt;/p&gt;

&lt;p&gt;夏一统， 商周继之，春秋战国乱之；秦一统，两汉继之，三国魏晋南北朝乱之；隋一统，大唐继之，五代十国宋辽金乱之；元一统，明清继之，民国乱之。&lt;/p&gt;

&lt;p&gt;2、红颜祸水，倾国倾城：&lt;/p&gt;

&lt;p&gt;夏亡于妹喜；商亡于妲己；西周亡于褒姒；吴亡于西施；秦以吕易嬴，赵姬之功；晋牛继马后，光姬之力；唐衰于杨玉环；明亡于陈圆圆；清败于太后慈禧。&lt;/p&gt;

&lt;p&gt;3、历史有无数的选择，选择在某个人手里：&lt;/p&gt;

&lt;p&gt;秦之李斯，助纣为虐，焚书坑儒；汉之王莽，书生治国，一塌糊涂；唐之安禄山，安史之乱，由盛转衰；宋之王安石，变法维新，由治而乱；明之吴三桂，一己之私，引狼入室；清之袁世凯，卖友求荣，反复无常。&lt;/p&gt;

&lt;p&gt;4、内忧小人干政，外戚、宦官、后宫；中忧官场腐败，官逼必然民反；外忧民族矛盾，异族虎视耽耽：&lt;/p&gt;

&lt;p&gt;历朝历代之灭亡，无不由此三者起。&lt;/p&gt;

&lt;p&gt;5、胜者王侯败者贼，历史即是：为胜者歌功颂德、败者落井下石的虚假陈述：&lt;/p&gt;

&lt;p&gt;胜即是刘邦，败即是项羽；胜即是李世民，败即是窦建德；胜即是朱元璋，败即是张士诚；胜是一国之君，败是流贼草寇。&lt;/p&gt;

&lt;p&gt;6、矫枉总是过正，其实过犹不及：&lt;/p&gt;

&lt;p&gt;秦尚法，汉即尚儒；唐重武轻文，宋即重文轻武；唐宋尚诗词，明清即尚八股。&lt;/p&gt;

&lt;p&gt;7、越是四分五裂，政治混乱，思想越光辉灿烂；越是大一统，政治稳定，思想越停滞不前。&lt;/p&gt;

&lt;p&gt;前者如春秋战国之百家争鸣，魏晋南北朝之三教合融；后者如秦之焚书坑儒，汉之独尊儒术，明之八股，清之文字狱。&lt;/p&gt;

&lt;p&gt;8、地域环境左右命运：&lt;/p&gt;

&lt;p&gt;中国自古东临太平洋，北接荒芜人烟的西伯利亚，西北是塔克拉玛干大沙漠，西南为喜马拉雅山，在这样一个封闭的环境之内生存，养成了国人含蓄内敛、保守中庸、消极忍耐的农耕性格。故历朝政府皆重农抑商，重伦理文采，轻科技实用；如夏政权在陕西、商政权在河南；西周政权在陕西、东周政权在河南；秦、西汉政权在陕西、东汉政权在河南；隋、唐政权在陕西、北宋政权在河南。五千年文明，有四千年历史皆在农耕最发达的中原地区上演，由此可见，中国一直都是以农耕为主的黄色文明。直到异族蒙古入主中原，定都北京，明清政权才随之坐落于此，中国的农耕地位才逐渐为之动摇。&lt;/p&gt;

&lt;p&gt;当政权东西对峙时，西强而东弱；南北对峙时，北强而南弱。原因也正是在于西和北更接近于游牧民族，两种文化的交融，自然比东南单纯的农耕文化多了一些强悍。然而，每一次异族依靠武力的入侵，又都会被汉文化迅速的同化。&lt;/p&gt;

&lt;p&gt;9、朝代之初，君强臣强；朝代之中，君强臣弱，朝代之末，君弱臣强：&lt;/p&gt;

&lt;p&gt;如唐之初，君有太宗，臣有房、杜；唐之中，君有玄宗，臣则为李林甫、杨国忠之流；唐末之君不足道也，臣却为虎狼之臣，如朱温之辈。历朝历代，莫不如此，岂有他哉！&lt;/p&gt;

&lt;p&gt;10、单以武治，刚且易折；单以文治，软弱可欺；文武结合，刚柔兼济，方能长治久安：&lt;/p&gt;

&lt;p&gt;如秦、元所向披靡，却迅速灰飞湮灭，两宋文化鼎盛，却屡被异族欺凌。惟汉、唐重文韬武略，方绵延三四百载，号称盛世，今已不再矣。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>VB VBS VBA Excel Programming</title>
   <link href="/2014/05/14/vb-vbs-vba-excel/"/>
   <updated>2014-05-14T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/05/14/vb-vbs-vba-excel</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Difference on VB VBA and VBS. Some points on Excel programming.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;vb-vbs-vba-difference&quot;&gt;VB VBS VBA difference&lt;/h2&gt;

&lt;p&gt;你们怎么都在讲VB啊.其实VBA是VB的分支(应该可以这样比喻吧),vba是依附于其它应用程序的,因此,它也较vb提供了更多的对象.同时vba不需要vb环境.反之,如果vb要使用vba下的对象,却需要vba的环境(即必须安装应用程序).
vbs是解释型脚本语言,vb尽管也是解释型语言,但它仍是可以编绎的(即可以在没有vb的环境中运行).vba也不能编绎,这点与vbs一样.
vbs本身没有提供任何窗口型对象(vb和vba的那些控件,同样有窗口).vbs提供最简洁环境,与任何应用程序具有无关性.
熟悉了vbs,就熟悉了vba的语法,但vba的环境,远比vbs丰富得多.
个人意见,想到哪写到哪.欢迎指正.&lt;/p&gt;

&lt;h2 id=&quot;vba-excel-programming&quot;&gt;VBA Excel programming&lt;/h2&gt;
&lt;p&gt;直到90 年代早期,使应用程序自动化还是充满挑战性的领域.对每个需要自动化的应用程
序,人们不得不学习一种不同的&lt;strong&gt;自动化语言&lt;/strong&gt;.例如:可以用EXCEL 的宏语言来使EXCEL 自动化,使
用WORDBASIC 使WORD 自动化,等等.微软决定让它开发出来的应用程序共享一种通用的自动化
语言–VisualBasicForApplication(VBA),可以认为VBA 是非常流行的应用程序开发
语言VASUALBASIC 的子集.实际上VBA 是&quot;寄生于&quot;VB 应用程序的版本.VBA 和VB 的区别包括如
下几个方面:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;VB 是设计用于创建标准的应用程序,而VBA 是使已有的应用程序(EXCEL 等)自动化&lt;/li&gt;
  &lt;li&gt;VB 具有自己的开发环境,而VBA 必须寄生于已有的应用程序.&lt;/li&gt;
  &lt;li&gt;要运行VB 开发的应用程序,用户不必安装VB,因为VB 开发出的应用程序是可执行文件
(*.EXE),而VBA 开发的程序必须依赖于它的&quot;父&quot;应用程序,例如EXCEL.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;指一系列EXCEL 能够执行的VBA语句。宏是由excel界面录制的（有后台代码）,实际还是保存成了vba代码，而vba是直接由代码编写的，宏的外观表现可由后台代码修改而变化。&lt;/p&gt;

&lt;p&gt;宏和VBA是不一样的。宏只是VBA中最简单的应用。宏能够自动执行一系列操作，是因为其背后是一组VBA的程序代码，在录制宏的过程中，计算机把记录的操作都转换成了VBA代码。&lt;/p&gt;

&lt;p&gt;Excel（包括其他Office 程序）允许用户录制一段宏，并将其记录为VBA 代码。对于开发者，使用这一功能，一方面可以节省时间，将录制的宏代码作为开发的基础，另一方面，对于不熟悉的操作，例如如何绘制图表，如何删除一行之类操作，可以录制一个宏并，通过查看其VBA 代码进行学习。录制的宏可以在VBA 集成开发环境（IDE）中修改编辑，可以为宏指定按钮、快捷键；而实际编写的代码也可以象宏一样在运行。&lt;/p&gt;

&lt;p&gt;宏实际上就是一个简单的VBA的Sub过程，它保存在模块里，以Sub开头，以End Sub结尾，执行时就从第一句逐句执行，直到End Sub结束。&lt;/p&gt;

&lt;p&gt;###录制宏的局限性
 宏代码绝不等于VBA，它只是VBA里最简单的运用，尽管许多Excel过程都可以用录制宏来完成，但是通过宏代码还是无法完成许多的工作，如：
（1）不可以建立公式，函数；
（2）录制的宏没有判断或循环的功能；
（3）不能进行人机交互；人机交互能力差,即用户无法进行输入,计算机无法给出提示
（4）无法显示用户窗体；
（5）无法与其他软件或文件进行互动。&lt;/p&gt;

&lt;p&gt;Refer to &lt;a href=&quot;http://t.excelhome.net/forum.php?mod=viewthread&amp;amp;tid=4172&amp;amp;highlight=&amp;amp;page=2&quot;&gt;什么是宏，什么是VBA，两者有区别吗？&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;excel-programming-basics&quot;&gt;Excel Programming Basics&lt;/h2&gt;

&lt;p&gt;如何打开VBA IDE编辑器&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;通过快捷键“ALT + F11”打开VB编辑器IDE&lt;/li&gt;
  &lt;li&gt;也可以通过Developer Mode打开VB和Macro&lt;/li&gt;
  &lt;li&gt;还可以在邮件点击work shett，选择View Code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;VBA中给变量赋值使用set和不使用set的区别
&apos;给普通变量赋值使用LET ，只是LET 可以省略。
&apos;给对象变量赋值使用SET，SET 不能省略。例如ADODB.RecordSet等对象。&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vb.net&quot; data-lang=&quot;vb.net&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;Sub AA()
    Dim arr As String
    arr = &quot;hello&quot; &apos;本句也可写成LET arr = &quot;hello&quot;
End Sub
Sub bb()
    Dim arr As String
    Set arr = &quot;hello&quot;  &apos; 这样写是错误的。
End Sub
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;VBA中变量用dim定义和不用dim定义而直接使用有何区别？
&apos;DIM 语句 的作用似乎声明变量并分配存储空间。
&apos;如果不指定数据类型或对象类型，也就是不用DIM定义，且在模块中没有 Deftype 语句，
&apos;则该变量按缺省设置是 Variant 类型。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Image and File</title>
   <link href="/2014/05/06/image-and-file/"/>
   <updated>2014-05-06T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/05/06/image-and-file</id>
   <content type="html">&lt;div class=&quot;message&quot;&gt;
注意这些方法细微区别。主要看是否background图片，是否relative/absolute定位，是否表格图片。
&lt;/div&gt;

&lt;p&gt;Add a file by markup.&lt;br /&gt;
&lt;a href=&quot;/assets/fx-3650P_3950P_EN.pdf&quot;&gt;A PDF&lt;/a&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Add a file by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;href&lt;/code&gt;. &lt;br /&gt;
&lt;a href=&quot;/assets/fx-3650P_3950P_EN.pdf&quot; target=&quot;_blank&quot;&gt;fx-3650P_3950P_EN&lt;/a&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Add an image by markup.
&lt;img src=&quot;/assets/plane.jpg&quot; alt=&quot;Test&quot; title=&quot;Optional title&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One way around this is to size images in relative units, rather than absolute pixel dimensions. The most common relative solution is to set the max-width of the image at 100%. Specifying only the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;width&lt;/code&gt; of images may cause a doubling or tripling of the cycles that many browsers must process to layout the new, resized page. While each of these cycles typically take less than a millisecond, they stack up, especially if there are multiple scalable elements on the page. Addressing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;height&lt;/code&gt; in the same declaration can reduce this issue.
&lt;img src=&quot;/assets/hknight.jpg&quot; alt=&quot;Hong Kong Night&quot; style=&quot;max-width:100%;height:auto;&quot; /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/plane.jpg&quot; alt=&quot;Hong Kong Night&quot; style=&quot;float:right; width:50%; margin-left:0.5rem; max-width:738px;&quot; /&gt;
A better, albeit more complex approach to fluid images is to measure the width of the image as a percentage of the overall width of the page. For example, let’s say you had an image that had a natural size of 500px × 300px in a 1200px wide document. Below 1200px, the document will be fluid. The calculation of how much width the image takes up as a percentage of the document is easy: (500 / 1200 ) × 100 = 41.66%.&lt;/p&gt;

&lt;p&gt;We can plug this number in as the width for the image; typically, this would be done inline, as each image will often be a different dimension. For this method, put the &lt;strong&gt;image before the text&lt;/strong&gt;.
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Place text over image, this is combination of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background url&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt;. For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;width&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;height&lt;/code&gt; of the image should be included. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt; is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10px&lt;/code&gt; which overwrites the default in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poole.css&lt;/code&gt; file.&lt;/p&gt;
&lt;div style=&quot;position:relative; background:url(/assets/hknight.jpg); width:738px; height:284px; border-radius:10px;&quot;&gt;
  &lt;div style=&quot;position:absolute; bottom:0.5em; left:0.5em; width:400px; font-weight:bold; color:#fff;&quot;&gt;(some text ...some text ...some text ...)&lt;/div&gt;
  &lt;p style=&quot;position:absolute; top:1em; right:2em; width:120px; padding:4px; background-color:#fff; font-weight:bold; font-size:11px;&quot;&gt;(some text ...some text ...some text ...)&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Place text over image, position not accurate.&lt;/p&gt;
&lt;div style=&quot;background:url(/assets/hknight.jpg) no-repeat; width:738px; height:284px; text-align:center; border-radius:10px;&quot;&gt;
  &lt;span style=&quot;color:#fcc&quot;&gt;some text ...&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;Place text over image, by &lt;span style=&quot;color:red; font-weight:bold&quot;&gt;table&lt;/span&gt;, position not accurate. No &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt; attribute here. So border angle is sharpe.&lt;/p&gt;
&lt;table border=&quot;0&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot;&gt;
&lt;tr&gt;
&lt;td width=&quot;738&quot; height=&quot;284&quot; background=&quot;/assets/hknight.jpg&quot; valign=&quot;bottom&quot;&gt;
&lt;FONT SIZE=&quot;+1&quot; COLOR=&quot;yellow&quot;&gt;some text ...&lt;/FONT&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Place text over image. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt; is acctually attribute of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;img&lt;/code&gt;. Attention: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;margin&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-width&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;overflow&lt;/code&gt; is already specified in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poole.css&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lanyon.css&lt;/code&gt; files. Here is just a complete example to show the method. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rgb(255,255,255)&lt;/code&gt; is called &lt;strong&gt;fallback color&lt;/strong&gt; for compatibility issue in that some browsers does not support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rgba&lt;/code&gt;. Similarly, this also applies to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hsl&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hsla&lt;/code&gt;.&lt;/p&gt;
&lt;div style=&quot;position:relative; overflow:hidden; border-radius:5px&quot;&gt;
  &lt;img src=&quot;/assets/hknight.jpg&quot; style=&quot;max-width:100%; height:auto; margin:0 0 0.5rem 0;&quot; /&gt;
  &lt;p style=&quot;position:absolute; left:100px; top:55px; background:rgb(255, 255, 255);background:rgba(255, 255, 255, 0.5); color:blue; padding:4px; margin:0.5em;&quot;&gt;(text accurately positioned)&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Place text over image with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CSS&lt;/code&gt; file support with css support. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;znhoo.css&lt;/code&gt; style file is already added to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_include/head.html&lt;/code&gt;.&lt;/p&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;public/css/znhoo.css&quot; /&gt;

&lt;div class=&quot;txtimg&quot;&gt;
  &lt;img src=&quot;/assets/hknight.jpg&quot; /&gt;
  &lt;div class=&quot;bl&quot;&gt;(text to appear at the bottom left of the image)&lt;/div&gt;
  &lt;p class=&quot;tr&quot;&gt; (text to appear at the top right of the image)&lt;/p&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Use the last two methods! They are very good and complete.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;reference&quot;&gt;Reference&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://demosthenes.info/blog/586/CSS-Fluid-Image-Techniques-for-Responsive-Site-Design&quot;&gt;CSS Fluid Image Techniques for Responsive Site Design&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://docs.webplatform.org/wiki/css/properties/background-image&quot;&gt;background-image&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://css-tricks.com/text-blocks-over-image/&quot;&gt;Text Blocks Over Image&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.htmldog.com/guides/css/intermediate/backgroundimages/&quot;&gt;Background Images&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://zhidao.baidu.com/question/296249405.html&quot;&gt;请问如何利用html代码在一个图片上加上文字&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://bbs.csdn.net/topics/120076193&quot;&gt;请问怎样能用css作出文字叠加在图片上的效果&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.the-art-of-web.com/css/textoverimage/&quot;&gt;CSS: Placing text over an inline image&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/CSSLint/csslint/wiki/Require-fallback-colors&quot;&gt;fallback color&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>INTERNET RESOURCES</title>
   <link href="/2014/04/08/internet-resource/"/>
   <updated>2014-04-08T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/04/08/internet-resource</id>
   <content type="html">&lt;div class=&quot;message&quot;&gt;
  This is the Internet resource links I think meaningful.
&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.newyorker.com/&quot;&gt;THE NEW YORKER&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.economist.com/&quot;&gt;The Economist&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://time.com/&quot;&gt;TIME&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.50pullups.com&quot;&gt;50 pullups&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Github Commands</title>
   <link href="/2014/04/05/github-commands/"/>
   <updated>2014-04-05T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/04/05/github-commands</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;This post focues on Git configuration and some commands. For complete Git principle and analysis refer to post &lt;em&gt;Git Architecture&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;checkout&quot;&gt;Checkout&lt;/h1&gt;
&lt;p&gt;If you ever &lt;strong&gt;modified&lt;/strong&gt; some files or folders. Then found them inappropriate, you can revert/discard the changes by &lt;strong&gt;checkout&lt;/strong&gt; command.&lt;/p&gt;

&lt;p&gt;For example, if you changed the file &lt;em&gt;file.txt&lt;/em&gt;, then you can use command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git checkout -- file.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command will copy the lasted committed &quot;file.txt&quot; from the git repository. The staging area and working tree are also updated.&lt;/p&gt;

&lt;p&gt;If you want to discard all the changes:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git checkout -- .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This command is fairly handy when you want to discard several changes across different files.&lt;/p&gt;

&lt;h1 id=&quot;clean&quot;&gt;Clean&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;git clean [-d] [-f] [-i] [-n] [-q] [-e &lt;pattern&gt;] [-x | -X] [--] [path…]&lt;/pattern&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cleans the working tree by recursively removing files that are not under version control, starting from the current directory.&lt;/p&gt;

&lt;p&gt;Normally, only files unknown to Git are removed, but if the &lt;span style=&quot;color:blue&quot;&gt;-x&lt;/span&gt; option is specified, ignored files are also removed. This can, for example, be useful to remove all build products.&lt;/p&gt;

&lt;p&gt;If any optional &lt;span style=&quot;color:blue&quot;&gt; [path…] &lt;/span&gt;arguments are given, only those paths are affected.&lt;/p&gt;

&lt;p&gt;If you have many untracked or ignored files in your repository, use command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clean -ndx [path]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; is to try a dry-run, only shows which files will be cleaned. For real action, remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; argument. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt; means untracked folders as well. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; means don’t use the standard ignore rules read from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt;. &lt;strong&gt;Therefore, gitignored files won&apos;t be ignored by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clean&lt;/code&gt; and will be removed&lt;/strong&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X&lt;/code&gt; means removing only files ignored by Git. Option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[path]&lt;/code&gt; is to only clean a sub-directory of current repository. For example, many &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; trailing files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_post&lt;/code&gt; folders:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clean -idx _post/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; is used for interactive mode which ask you yes or not when cleaning files. To simplify things, replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; which will force removing without hints. Most of the time, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*~&lt;/code&gt; files are ignored by git, so we need to include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; option.&lt;/p&gt;

&lt;h4 id=&quot;reference&quot;&gt;Reference&lt;/h4&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://gitready.com/beginner/2009/01/16/cleaning-up-untracked-files.html&quot;&gt;cleaning up untracked files&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;upload-local-directory-as-a-repository&quot;&gt;Upload local directory as a repository&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;Go to Github web, create a repository. You can init the repository &lt;strong&gt;with&lt;/strong&gt; or &lt;strong&gt;without&lt;/strong&gt; a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README.md&lt;/code&gt; file, which makes a difference on the procedures below.&lt;/li&gt;
  &lt;li&gt;Go to the local directory for commands&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git init&lt;/code&gt;. Initialize the local directory as a Git repository. This will creat a hiden floder called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; all the git-related stuff will be there.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add .&lt;/code&gt; Add the files in your new local repository. This stages them for the first commit.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -m &apos;First commit&apos;&lt;/code&gt;. Commits the tracked changes and prepares them to be pushed to a remote repository.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git remote add origin &amp;lt;remote repository URL&amp;gt;&lt;/code&gt;. The remote repository URL is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https&lt;/code&gt; URL of the repository you created in the 1st step.
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git remote -v&lt;/code&gt; Verifies the new remote URL.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;[optional] If you create the remote repository &lt;strong&gt;with&lt;/strong&gt; a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REAMDME.md&lt;/code&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull origin master&lt;/code&gt; to pull the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README.md&lt;/code&gt; first, otherwise you could not push local directory contents to remote. The git assumes your local copy lags behind of the remote origin.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push origin master&lt;/code&gt;. Pushes the changes in your local repository up to the remote repository you specified as the origin.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;reference-1&quot;&gt;Reference&lt;/h4&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/&quot;&gt;adding an existing project to github using the comand line&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;gitignore&quot;&gt;gitignore&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gitignore&lt;/code&gt; files can ignore files that will not be pushed to remote repository.There are several kinds of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gitignore&lt;/code&gt; files including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore_global&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git/info/exclude&lt;/code&gt;.&lt;/p&gt;

&lt;h4 id=&quot;reference-2&quot;&gt;Reference&lt;/h4&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.github.com/articles/ignoring-files/&quot;&gt;ignoring files&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://git-scm.com/docs/gitignore&quot;&gt;gitignore&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;reference-3&quot;&gt;Reference&lt;/h1&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://rogerdudler.github.io/git-guide/&quot;&gt;A very good simple cheatsheet&lt;/a&gt;. It is not a good tutorial. But you can refer to it as you forget something.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>顶级域名不能设置DNS CNAME记录</title>
   <link href="/2014/03/06/auth-domain-no-cname/"/>
   <updated>2014-03-06T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/03/06/auth-domain-no-cname</id>
   <content type="html">&lt;p&gt;要用CDN加速，那么custom domain (无论是top还是sub的）必须指向username.github.io，不能直接指向username.github.io的ip地址。这样，由于是指向域名，而不是具体ip地址，CDN动态的根据访问者的位置来返回一个username.github.io的ip地址，这个ip地址和访问者的ip地址很近。如果是是直接指向一个固定的ip地址，那就只能从那个地址访问custom domain了。&lt;/p&gt;

&lt;p&gt;那么如何指向username.github.io呢？如果是subdomain，那好办，直接建立一条DNS CNAME记录，例如www CNAME username.github.io。如果是top domain，就稍微复杂些。Top domain是原理上不能设置CNAME记录，所以@ CNAME username.github.io这样的dns CNAME是不合法的。除非DNS provider 支持 CNAME flattening、ALIAS、ANAME，不过这些不是标准DNS协议，以来DNS provider服务。&lt;/p&gt;

&lt;p&gt;这里解释一下为何top domain不能有CNAME记录。因为&quot;A CNAME record is not allowed to coexist with any other data.&quot;也就是说如果为一个域名建立了一条CNAME记录，那么这个域名就不能有其他的dns记录了。一个域名一旦有CANME记录，说明它只能用作域名转换用，不能再有其他的作用。A CNAME-record cannot exist with any other records for the same name, because a name cannot both be an alias (CNAME) and something else at the same time.这句话里的name就是我指的域名，或者说是dns的记录中左边的那个值。如果你建立一条example.com CNAME username.github.io，那么它会和所有其它的以example.com开头的DNS记录冲突，而事实是这样的记录必定存在！这样的记录有SOA，NS记录，这些记录平常我们是看不到的。当你在域名提供商那里注册域名时，提供商会默默的为你建立SOA NS记录，这些记录就是以example.com开头的DNS记录，具体例子参考&lt;a href=&quot;http://support.dnsimple.com/articles/ns-record/&quot;&gt;What is a NS Record?&lt;/a&gt;和&lt;a href=&quot;http://support.dnsimple.com/articles/soa-record/&quot;&gt;What is a SOA Record?&lt;/a&gt;。SOA 和 NS记录，是必须存在的，必不可少，否则域名都无法注册。好了，既然SOA NS这样的记录必须存在，那么以example.com开头的CNAME记录就不能建立了。记住，不能建立CNAME记录，但可以建立A记录，RFC并没有说A记录不能和其他的记录共存。&lt;/p&gt;

&lt;p&gt;现在来回顾一下为何以www.example.com开头的CNAME记录可以存在？因为域名提供商不会默默为你建立其它的以www.example.com开头的域名。如果你自己同时建立两条以www.example.com开头的记录，并且其中一条是CNAME记录，那同样也不行！！但这种情况很少。为何会出现要求建立顶级郁闷开头的CNAME记录呢？因为这些需求以个人为主，个人一般来说就是一个博客网站，不会有其他的如mail ftp等需求，都希望顶级域名访问自己的博客。&lt;/p&gt;

&lt;p&gt;总之一旦有一个以label (any name)开头的CNAME记录，就不能再有其它的以label开头的任何类型的DNS记录了！此时label只能唯一用作域名转换。CNAME的作用就是把左边的label（别名）换成右边的真正的域名。&lt;/p&gt;

&lt;p&gt;另外，前面讨论中多次提到&lt;strong&gt;顶级域名&lt;/strong&gt;。&lt;strong&gt;顶级域名&lt;/strong&gt;是一个相对概念，譬如example.com相对www.example.com是顶级域名，但是example.com本身也有顶级域名com。所以前面的讨论中&lt;strong&gt;顶级域名&lt;/strong&gt;是针对你手中已经有点最高级的域名来说的，譬如我在freenom注册了域名example.tk，那么对我来说，我现有的最高级的域名就是它了。其他的譬如www.example.tk, mail.example.tk, ftp.example.tk都是我的sub domain。假如你的最高级域名是三级的blog.example.com，那么它就是你的顶级域名，photo.blog.example.com就是sub domain，这个情况同样适用于上面的CNAME问题讨论。&lt;/p&gt;

&lt;p&gt;参考资料：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://support.simpledns.com/kb/a94/why-cant-i-create-a-cname-record-for-the-zone-name-itself.aspx&quot;&gt;Why can&apos;t I create a CNAME record for the zone name itself?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/656009/how-to-overcome-root-domain-cname-restrictions&quot;&gt;How to overcome root domain CNAME restrictions?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/655235/is-root-domain-cname-to-other-domain-allowed-by-dns-rfc&quot;&gt;Is Root domain CNAME to other domain allowed by DNS RFC?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://serverfault.com/questions/613829/why-cant-a-cname-record-be-used-at-the-apex-of-a-domain/613830#613830&quot;&gt;Why can&apos;t a CNAME record be used at the apex of a domain?&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>Github Page Domain CDN Acceleration</title>
   <link href="/2014/03/05/github-domain-cdn/"/>
   <updated>2014-03-05T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/03/05/github-domain-cdn</id>
   <content type="html">&lt;div class=&quot;message&quot;&gt;
     Github page supports CDN acceleration service. How to do it?
&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;Default domain&lt;/em&gt;&lt;br /&gt;
 The github default domain is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;username.github.io&lt;/code&gt; which is also a &lt;em&gt;subdomain&lt;/em&gt;. But usually we need to use our own domain for blog. Personal domain may be top domain or subdomain. Subdomain is like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.example.com&lt;/code&gt; while top domain is like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt;. Github names &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;,&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alias&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ANAME&lt;/code&gt; all as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apex&lt;/code&gt; domain (record). Here &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apex&lt;/code&gt; domain acctually is not a domain but a domain dns record.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Acceleration&lt;/em&gt;&lt;br /&gt;
The key is to set a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; record for your github page &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;username.github.io&lt;/code&gt;. For example if you have a top domain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt;, A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; record is like:&lt;/li&gt;
&lt;/ol&gt;

&lt;table&gt;
 &lt;thead&gt;
  &lt;tr&gt;
   &lt;th&gt;Name&lt;/th&gt;
   &lt;th&gt;Type&lt;/th&gt;
   &lt;th&gt;Target&lt;/th&gt;
  &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
  &lt;tr&gt;
   &lt;td&gt;www&lt;/td&gt;
   &lt;td&gt;CNAME&lt;/td&gt;
   &lt;td&gt;username.github.io&lt;/td&gt;
  &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This means subdomain address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.example.com&lt;/code&gt; will be redirected to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;username.github.io&lt;/code&gt;.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;CNAME&lt;/em&gt; and &lt;em&gt;Top domain&lt;/em&gt;&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; does not support top domain. The following three lines are all illegal unless your DNS provider &lt;a href=&quot;https://support.cloudflare.com/hc/en-us/articles/200169056-CNAME-Flattening-RFC-compliant-support-for-CNAME-at-the-root&quot;&gt;supports CNAME flattening&lt;/a&gt; (i.e. Clouflare), ALIAS and ANAME.&lt;/li&gt;
&lt;/ol&gt;

&lt;table&gt;
 &lt;thead&gt;
  &lt;tr&gt;
   &lt;th&gt;Name&lt;/th&gt;
   &lt;th&gt;Type&lt;/th&gt;
   &lt;th&gt;Target&lt;/th&gt;
  &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
  &lt;tr&gt;
   &lt;td&gt;example.com&lt;/td&gt;
   &lt;td&gt;CNAME&lt;/td&gt;
   &lt;td&gt;username.github.io&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;@&lt;/td&gt;
   &lt;td&gt;CNAME&lt;/td&gt;
   &lt;td&gt;username.github.io&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;/td&gt;
   &lt;td&gt;CNAME&lt;/td&gt;
   &lt;td&gt;username.github.io&lt;/td&gt;
  &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If you set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; like this, it will direct all your other subdomains like mail, ftp etc to your github page. Refer to &lt;a href=&quot;https://help.github.com/articles/tips-for-configuring-a-cname-record-with-your-dns-provider/&quot;&gt;custom subdomain&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Do not use wildcard DNS records (e.g. *.example.com) with GitHub Pages! A wildcard DNS record will allow anyone to host a GitHub Pages site at one of your subdomains.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Can I use my top domain for acceleration? Yes, but not easy! First, your DNS provider must support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alias DNS Record&lt;/code&gt; which is not a standard DNS record. Only a few DNS provider support this with fees, like &lt;strong&gt;dnssimple&lt;/strong&gt;. Refer to &lt;a href=&quot;http://support.dnsimple.com/articles/alias-record/&quot;&gt;What is an ALIAS record?&lt;/a&gt; and &lt;a href=&quot;http://support.dnsimple.com/articles/domain-apex-heroku/&quot;&gt;Pointing the Domain Apex to Heroku&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;Procedures&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Add a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; file (or &lt;a href=&quot;https://help.github.com/articles/adding-or-removing-a-custom-domain-for-your-github-pages-site/&quot;&gt;by Github setting&lt;/a&gt;) at the root directory of github pages. You may find it uncessary at first. If you don&apos;t add this file, only the first time you enter the custom domain url works as you wish. If you further click some other links in the blog (i.e. a post), you will find the url changes to original &lt;em&gt;username.github.io&lt;/em&gt;. This looks ugly. What was worse, The webbrower tab will not show the blog title.&lt;/p&gt;

    &lt;p&gt;Add your custom domain to your GitHub Pages site&apos;s repository before configuring your domain name with your DNS provider.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; file, you can put only one line namely &lt;em&gt;www.example.com&lt;/em&gt; there. Now Github handles everything in your jekyll blog with address &lt;em&gt;www.example.com&lt;/em&gt; not the original &lt;em&gt;username.github.io&lt;/em&gt;. Attention! Put bare address. Don&apos;t add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Next need DNS support. I choose &lt;strong&gt;freenom&lt;/strong&gt; to register my top domain &lt;em&gt;example.tk&lt;/em&gt;. Why top domain? Not subdomain? Don&apos;t worry! &lt;em&gt;Freenom&lt;/em&gt; supports top domain, why not get one? Yes, get the top domain. Then we can set a &lt;em&gt;CNAME&lt;/em&gt; DNS record! Refer to &lt;a href=&quot;https://my.freenom.com/knowledgebase.php?action=displayarticle&amp;amp;id=4&quot;&gt;How to setup A, MX, CNAME…&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; record is to transfer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WWW&lt;/code&gt; subdomain of &lt;em&gt;example.tk&lt;/em&gt; (namely &lt;em&gt;www.example.tk&lt;/em&gt;) to &lt;em&gt;username.github.io&lt;/em&gt;. Now wait for a while, it will be fine. Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dig www.example.tk&lt;/code&gt; to test your result. Refer to &lt;a href=&quot;https://help.github.com/articles/tips-for-configuring-a-cname-record-with-your-dns-provider/#configuring-a-custom-subdomain-with-your-dns-provider&quot;&gt;use the dig command&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;But if you want &lt;em&gt;example.tk&lt;/em&gt; also points to &lt;em&gt;username.github.io&lt;/em&gt;, what should be done? As mentioned above we cannot use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt;. What is worse, &lt;strong&gt;freenom&lt;/strong&gt; does not support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alias&lt;/code&gt; DNS record like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnssimple&lt;/code&gt; does. However we can set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; record for the top domain alghtough it does not support CDN. Please refer to &lt;a href=&quot;https://help.github.com/articles/tips-for-configuring-an-a-record-with-your-dns-provider/&quot;&gt;configuring an A record on Github&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
 &lt;thead&gt;
  &lt;tr&gt;
   &lt;th&gt;Name&lt;/th&gt;
   &lt;th&gt;Type&lt;/th&gt;
   &lt;th&gt;Target&lt;/th&gt;
  &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;/td&gt;
   &lt;td&gt;A&lt;/td&gt;
   &lt;td&gt;192.30.252.153&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;&lt;/td&gt;
   &lt;td&gt;A&lt;/td&gt;
   &lt;td&gt;192.30.252.154&lt;/td&gt;
  &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
  &lt;li&gt;Now you can access your blog from both subdomain and top domain. Although top domain does not support CDN individually, but if both subdomain CNAME and top domain A records are configured, github itsefl will create redirect between the two based on the &lt;strong&gt;CNAME file&lt;/strong&gt; in the github page root directory. Refer to &lt;a href=&quot;https://help.github.com/articles/tips-for-configuring-an-a-record-with-your-dns-provider/#configuring-a-www-subdomain&quot; target=&quot;_blank&quot;&gt;Configuring a www subdomain&lt;/a&gt;. Since the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; file in github pages are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.example.com&lt;/code&gt;, then when you input &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt; in your browser, github will redirects you to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.example.com&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;message&quot;&gt;
Till now, both subdomain and top domain support CDN!
&lt;/div&gt;

&lt;p&gt;For more detailed Top domain DNS CNAME discussion refer to &lt;a href=&quot;/2014/03/06/%E9%A1%B6%E7%BA%A7%E5%9F%9F%E5%90%8D%E4%B8%BA%E4%BD%95%E4%B8%8D%E8%83%BD%E8%AE%BEDNS%20CNAME%E8%AE%B0%E5%BD%95/&quot;&gt;顶级域名不能设置DNS CNAME记录&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Reference&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.github.com/articles/setting-up-a-custom-domain-with-github-pages/&quot;&gt;Setting up a custom domain with GitHub Pages&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://m.blog.csdn.net/blog/chuchus/38964175&quot;&gt;Github Pages 静态网页建站&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://webmasters.stackexchange.com/questions/56826/do-i-set-a-dns-a-record-for-the-new-github-pages-to-use-their-cdn&quot;&gt;Do I set a DNS A Record for the new GitHub Pages to use their CDN?&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/blog/1715-faster-more-awesome-github-pages&quot;&gt;Faster, More Awesome GitHub Pages&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>HTML CSS JS PHP MYSQL collaboration</title>
   <link href="/2014/02/12/html-js-css-php-mysql/"/>
   <updated>2014-02-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/02/12/html-js-css-php-mysql</id>
   <content type="html">&lt;div class=&quot;message&quot;&gt;
This post will introduce the basic components of a web system both on the front end and the back end.
&lt;/div&gt;

&lt;table style=&quot;width:100%&quot;&gt;
 &lt;tr&gt;
  &lt;td&gt;HTML&lt;/td&gt;
  &lt;td&gt;Content and Structure&lt;/td&gt;
  &lt;td&gt;text, images, talbes, forms, etc&lt;/td&gt;
  &lt;td&gt;run by browser&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;CSS&lt;/td&gt;
  &lt;td&gt;Style and Presentation&lt;/td&gt;
  &lt;td&gt;color, fonts, background, margins, paddings, etc&lt;/td&gt;
  &lt;td&gt;run by browser&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Javascript&lt;/td&gt;
  &lt;td&gt;Client Side Scripting&lt;/td&gt;
  &lt;td&gt;dynamic user interaction, popups, form validation, drop box etc&lt;/td&gt;
  &lt;td&gt;run by browser&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;PHP&lt;/td&gt;
  &lt;td&gt;Server Side Scripting&lt;/td&gt;
  &lt;td&gt;server side logic and data processing&lt;/td&gt;
  &lt;td&gt;run by server&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;MySQL&lt;/td&gt;
  &lt;td&gt;Data Management&lt;/td&gt;
  &lt;td&gt;stores all sorts of data needed by a website&lt;/td&gt;
  &lt;td&gt;run by server&lt;/td&gt;
&amp;lt;/table&amp;gt;

## Useful resources
1. [Web development tutorials](http://www.yourwebskills.com/contents.php) covers verything for web programming.
2. [Understanding PHP, MySQL, HTML and CSS](http://www.youtube.com/watch?v=tAm1YwFIWuY) is a simple video tutorial from front end to back end.
&lt;/tr&gt;&lt;/table&gt;
</content>
 </entry>
 
 <entry>
   <title>Jekyll Poole Lanyon Blog Building</title>
   <link href="/2014/02/04/jekyll-poole-lanyon-blog-building/"/>
   <updated>2014-02-04T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/02/04/jekyll-poole-lanyon-blog-building</id>
   <content type="html">&lt;div class=&quot;message&quot;&gt;
 This is to record the process of build the blog process.
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;The most important reference is &lt;a href=&quot;http://joshualande.com/jekyll-github-pages-poole/&quot;&gt;How I Created a Beautiful and Minimal Blog Using Jekyll, Github Pages, and poole&lt;/a&gt;, &lt;a href=&quot;https://github.com/poole/lanyon&quot;&gt;Lanyon&lt;/a&gt; and &lt;a href=&quot;https://github.com/poole&quot;&gt;Poole&lt;/a&gt; on Github.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;procedure&quot;&gt;Procedure&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt; Install git command&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ sudo apt-get install git&lt;/code&gt;&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ git config --global ...&lt;/code&gt; For configuration commands refer to official website on &quot;Set up Git&quot;.&lt;/p&gt;

&lt;p&gt;Mainly two commands:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global user.name &quot;YOUR NAME&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config --global user.email &quot;YOUR EMAIL&quot;&lt;/code&gt;. You can hide your email address by &lt;a href=&quot;https://help.github.com/articles/keeping-your-email-address-private/&quot;&gt;Keeping your email address private&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt; Create user pages&lt;br /&gt;
Create a empty repository called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;username.github.com&lt;/code&gt; on Github web without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;README&lt;/code&gt; file.&lt;br /&gt;
&lt;strong&gt;3&lt;/strong&gt; Ubuntu Command lines&lt;br /&gt;
Copy &lt;em&gt;Lanyon&lt;/em&gt; locally.&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ git clone https://github.com/poole/lanyon.git username.github.com&lt;/code&gt;&lt;br /&gt;
Enter the new cloned repository.&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ cd username.github.com&lt;/code&gt;&lt;br /&gt;
Set remote repository to sync later on.&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ git remote set-url origin https://github.com/username/username.github.com.git&lt;/code&gt;&lt;br /&gt;
Push locall repository to remote.&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ git push origin master&lt;/code&gt;&lt;br /&gt;
&lt;strong&gt;4&lt;/strong&gt; Visit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;username.github.io&lt;/code&gt;&lt;br /&gt;
What you see it not yours, all the contents are from &lt;em&gt;Lanyon&lt;/em&gt;. We need to modify the contents for our own use. We should firstly validate the modification before push to remote repository. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Jekyll&lt;/code&gt; can do that validation.&lt;br /&gt;
&lt;strong&gt;5&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Jekyll&lt;/code&gt;&lt;br /&gt;
For installation, refer to &lt;a href=&quot;http://michaelchelen.net/81fa/install-jekyll-2-ubuntu-14-04/&quot;&gt;Install Jekyll 2 on Ubuntu 14.04&lt;/a&gt; and &lt;a href=&quot;http://jekyllrb.com/docs/installation/&quot;&gt;Official site&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt-get install ruby ruby-dev&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby-dev&lt;/code&gt; must be installed otherwise see &lt;a href=&quot;http://stackoverflow.com/questions/10725767/error-installing-jekyll-native-extension-build&quot;&gt;Error Installing Jekyll - Native Extension Build&lt;/a&gt;.&lt;/p&gt;

    &lt;p&gt;The reference links require installing of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rubygems&lt;/code&gt;, which is not necessary now. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rubygems&lt;/code&gt; package now is a purly virtual package and part of the real package &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby&lt;/code&gt;. See &lt;a href=&quot;http://ubuntuforums.org/showthread.php?t=1586035&amp;amp;s=4192711d774022d15589452169ca70a1&quot;&gt;can not install rubygems1.9.1 on Maverick Meerkat rc&lt;/a&gt;. You can test it by command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dpkg -L ruby&lt;/code&gt;. It shows &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gem&lt;/code&gt; is already installed by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby&lt;/code&gt; package.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo gem install jekyll&lt;/code&gt;. This might take a while.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt-get install nodejs&lt;/code&gt;  &lt;span style=&quot;color:blue&quot;&gt;There is an issue that causes Jekyll to require a JavaScript runtime even if it will not be used. Installing nodejs helps solve the issue&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll -v&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Jekyll comes with a built-in development server that will allow you to preview what the generated site will look like in your browser locally by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:4000&lt;/code&gt;. You can try now:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ jekyll server/serve/s&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;username.github.com&lt;/code&gt; directory&lt;/li&gt;
  &lt;li&gt;Open browser enter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;localhost:4000&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There you go! You can see a local copy of the repository. What you need to do now is to modify the contents locally for personal use.&lt;/p&gt;

&lt;h2 id=&quot;6-modification&quot;&gt;6 Modification&lt;/h2&gt;
&lt;p&gt;The first is to modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; configuration file such as contact info, blog title, etc.
The &lt;strong&gt;url&lt;/strong&gt; varialble in &lt;em&gt;_config.yml&lt;/em&gt;, I found it not useful. Remove it.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;baseurl&lt;/strong&gt; setting, refer to &lt;a href=&quot;https://github.com/poole/poole#usage&quot;&gt;4. Serving it up&lt;/a&gt; section.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If you&apos;re using a custom domain name, leave it as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;. Then modify the &lt;strong&gt;CNAME&lt;/strong&gt; file to point to new domain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.fangxiang.tk&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;If you&apos;re not using a custom domain name, modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;baseurl&lt;/code&gt; in &lt;em&gt;_config.yml&lt;/em&gt; to point to your GitHub Pages URL. Example: for a repo at github.com/username/poole, use http://username.github.io/poole/. Be sure to include the trailing slash.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Sidebar&lt;/strong&gt; &quot;Download&quot; and &quot;Github Project&quot; items does not work. Because &lt;em&gt;custom variable&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;site.github.repo&lt;/code&gt; is not defined in &lt;em&gt;_config.yml&lt;/em&gt;. The &lt;em&gt;site.github.repo&lt;/em&gt; is used in &lt;em&gt;_include/sidebar.html&lt;/em&gt;. Just add two lines in &lt;em&gt;_config.yml&lt;/em&gt; as follows. Pay attention to the indent of the second line.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;github&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;	&lt;span class=&quot;nx&quot;&gt;https&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;//github.com/outsinre/outsinre.github.com&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Though the problem was solved, I don&apos;t need the two sidebar items. So I removed them from _config.yml. Correspondingly, the lines in &lt;em&gt;_include/sidebar.html&lt;/em&gt; should also be removed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disqus&lt;/strong&gt; comments. Firsly, create a file &lt;em&gt;comments.html&lt;/em&gt; and add two lines:&lt;/p&gt;

&lt;p&gt;{% if page.comments %}&lt;/p&gt;

&lt;p&gt;{% endif %}&lt;/p&gt;

&lt;p&gt;Then paste the DISQUS universal code between the two lines. The &lt;em&gt;comments.html&lt;/em&gt; should be placed under &lt;em&gt;_include&lt;/em&gt; folder. After that, in &lt;em&gt;_layout/post.html&lt;/em&gt;, &lt;em&gt;_layout/page.html&lt;/em&gt;, &lt;em&gt;_layout/default.html&lt;/em&gt; files, add a line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{% include comments.html %}&lt;/code&gt;. Also in the very front add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;comments: true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What is DISQUS universal code? First, in DISQUS setup, add a site identifier, i.e. &lt;em&gt;jekylldq&lt;/em&gt;. Then, QISQUS will generate the universal code automatically for you. Lastly, just copy and paste it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Archive&lt;/strong&gt; page added based on the reference at the beginning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subscribe&lt;/strong&gt; page added by modifying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_include/sidebar.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;znhoo.css&lt;/strong&gt; added in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public/css/znhoo.css&lt;/code&gt;, especially for blog &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-align: justify&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Site icon&lt;/strong&gt; changed referring to &lt;a href=&quot;http://modernweb.com/2013/10/28/building-a-blog-with-jekyll/&quot;&gt;icons&lt;/a&gt;. Check the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_include/head.html&lt;/code&gt; for where is icon defined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;read more…&lt;/strong&gt;* to only display the first paragraph of a post. Only need to modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.html&lt;/code&gt; file. The original is to display the post content completely:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{{ post.content }}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;but now replaced by:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{{ post.excerpt | remove: &apos;&amp;lt;p&amp;gt;&apos; | remove: &apos;&amp;lt;/p&amp;gt;&apos; }}

{% if post.content.size &amp;gt; 500 %}
  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;a href=&quot;{{ post.url }}&quot;&amp;gt;Read more...&amp;lt;/a&amp;gt;
{% endif %}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;code line numbers&lt;/strong&gt; refer to &lt;a href=&quot;http://demisx.github.io/jekyll/2014/01/13/improve-code-highlighting-in-jekyll.html&quot; target=&quot;_blank&quot;&gt;Improve Code Highlighting in a Jekyll-based Blog Site&lt;/a&gt;. Especially pay due attention to its comments. How? Add several lines for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;public/css/syntax.css&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;cm&quot;&gt;/* display code line number; the line number is displayed aside from the code separated by a vertical line */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;highlight&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineno&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ccc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;px&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solid&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ccc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;highlight&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pre&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;white&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;space&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* exclude line numbers from copy-paste user operations; if you copy the code, the line numbers are also copied, so this line is to disable line number copy */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;highlight&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineno&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;webkit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;moz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/* override text selection hightlighting for line numbers; although the above line disables line number copy, but when you select the code, line numbers are also selected which looks ugly; the transparent color will help erase this */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;moz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transparent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Mozilla specific */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lineno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transparent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Other major browsers */&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;baseurl&lt;/strong&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; file. Please refer to &lt;a href=&quot;http://jekyllrb.com/docs/github-pages/&quot;&gt;GitHub Pages&lt;/a&gt;. Basically, pay attention to the &lt;em&gt;leading slash&lt;/em&gt; and &lt;em&gt;trailing slash&lt;/em&gt; issue when writing post. It is better to include the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;site.baseurl&lt;/code&gt; when accessing files. Don&apos;t use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;. Because the blog might be migrated to some other places or to a project github pages in the future, which causes compatibility issue. For example, to include an image in post:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;img&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ site.baseurl }}assets/hknight.jpg&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you replace:
`
{{ site.baseurl }}
`
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;, it is fine with user github page. But if the blog is migrated to project github page, then it does not work. You have to change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/project-name/&lt;/code&gt; in your post. If you have many such posts, it is a big trouble. However, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;site.baseurl&lt;/code&gt; works fine. The only place you need to change is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;fonts&lt;/strong&gt; setting.
Firstly, Open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layman.css&lt;/code&gt; and search for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-family&lt;/code&gt;, I removed all the fonts related to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PT&lt;/code&gt; like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PT Sans&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PT Serif&lt;/code&gt;. Then commented out the line:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700%7CPT+Sans:400&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head.html&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;Some fun facts about the setup of Poole project include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Built for &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Developed on GitHub and hosted for free on &lt;a href=&quot;https://pages.github.com&quot;&gt;GitHub Pages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Coded with &lt;a href=&quot;http://sublimetext.com&quot;&gt;Sublime Text 2&lt;/a&gt;, an amazing code editor&lt;/li&gt;
  &lt;li&gt;Designed and developed while listening to music like &lt;a href=&quot;https://soundcloud.com/maddecent/sets/blood-bros-series&quot;&gt;Blood Bros Trilogy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have questions or suggestions? &lt;a href=&quot;https://twitter.com/mdo&quot;&gt;Contact Poole author on Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introducing Lanyon</title>
   <link href="/2014/01/02/introducing-lanyon/"/>
   <updated>2014-01-02T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/01/02/introducing-lanyon</id>
   <content type="html">&lt;p&gt;Lanyon is an unassuming &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; theme that places content first by tucking away navigation in a hidden drawer. It&apos;s based on &lt;a href=&quot;http://getpoole.com&quot;&gt;Poole&lt;/a&gt;, the Jekyll butler.&lt;/p&gt;

&lt;h3 id=&quot;built-on-poole&quot;&gt;Built on Poole&lt;/h3&gt;

&lt;p&gt;Poole is the Jekyll Butler, serving as an upstanding and effective foundation for Jekyll themes by &lt;a href=&quot;https://twitter.com/mdo&quot;&gt;@mdo&lt;/a&gt;. Poole, and every theme built on it (like Lanyon here) includes the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Complete Jekyll setup included (layouts, config, &lt;a href=&quot;/404&quot;&gt;404&lt;/a&gt;, &lt;a href=&quot;/atom.xml&quot;&gt;RSS feed&lt;/a&gt;, posts, and &lt;a href=&quot;/about&quot;&gt;example page&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Mobile friendly design and development&lt;/li&gt;
  &lt;li&gt;Easily scalable text and component sizing with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rem&lt;/code&gt; units in the CSS&lt;/li&gt;
  &lt;li&gt;Support for a wide gamut of HTML elements&lt;/li&gt;
  &lt;li&gt;Related posts (time-based, because Jekyll) below each post&lt;/li&gt;
  &lt;li&gt;Syntax highlighting, courtesy Pygments (the Python-based code snippet highlighter)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;lanyon-features&quot;&gt;Lanyon features&lt;/h3&gt;

&lt;p&gt;In addition to the features of Poole, Lanyon adds the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Toggleable sliding sidebar (built with only CSS) via &lt;strong&gt;☰&lt;/strong&gt; link in top corner&lt;/li&gt;
  &lt;li&gt;Sidebar includes support for textual modules and a dynamically generated navigation with active link support&lt;/li&gt;
  &lt;li&gt;Two orientations for content and sidebar, default (left sidebar) and &lt;a href=&quot;https://github.com/poole/lanyon#reverse-layout&quot;&gt;reverse&lt;/a&gt; (right sidebar), available via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;body&amp;gt;&lt;/code&gt; classes&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/poole/lanyon#themes&quot;&gt;Eight optional color schemes&lt;/a&gt;, available via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;body&amp;gt;&lt;/code&gt; classes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/poole/lanyon#readme&quot;&gt;Head to the readme&lt;/a&gt; to learn more.&lt;/p&gt;

&lt;h3 id=&quot;browser-support&quot;&gt;Browser support&lt;/h3&gt;

&lt;p&gt;Lanyon is by preference a forward-thinking project. In addition to the latest versions of Chrome, Safari (mobile and desktop), and Firefox, it is only compatible with Internet Explorer 9 and above.&lt;/p&gt;

&lt;h3 id=&quot;download&quot;&gt;Download&lt;/h3&gt;

&lt;p&gt;Lanyon is developed on and hosted with GitHub. Head to the &lt;a href=&quot;https://github.com/poole/lanyon&quot;&gt;GitHub repository&lt;/a&gt; for downloads, bug reports, and features requests.&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Markdown Post Example</title>
   <link href="/2014/01/01/example-post-writing/"/>
   <updated>2014-01-01T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2014/01/01/example-post-writing</id>
   <content type="html">&lt;div class=&quot;message&quot;&gt;
  Howdy! This is an example blog post that shows several types of HTML content supported in this theme.
&lt;/div&gt;

&lt;h2 id=&quot;code-block&quot;&gt;Code Block&lt;/h2&gt;

&lt;p&gt;Use &lt;strong&gt;&lt;ins&gt;`&lt;/ins&gt;&lt;/strong&gt; to enclose a code snippet.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int main(void){ printf(&quot;hello, world!&quot;); return 1; }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Or you can use &lt;strong&gt;tab&lt;/strong&gt; key:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int main(void){ ...}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Another way for code highlight is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pygments&lt;/code&gt; by default (refer to &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&apos;s&lt;/a&gt; offical site):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{% hightlight ruby linenos %}
{% endhight %}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby&lt;/code&gt; with any languages &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pygments&lt;/code&gt; supports (refer to &lt;a href=&quot;http://pygments.org/languages/&quot;&gt;languages&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;An example. Pay attention to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linenos&lt;/code&gt; to display code line numbers.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello, world!)&apos;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;    return 1;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you want to insert code in list, use &lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_ to enclose the code block. The code block needn&apos;t any indent. But the _&lt;/code&gt;&lt;/em&gt; needs an extra indent (4 spaces or 1 tab) plus the list&apos;s indents.&lt;/p&gt;

&lt;h2 id=&quot;how-to-write-about-jekyll-itself-in-jkeyll&quot;&gt;How to write about Jekyll itself in Jkeyll?&lt;/h2&gt;

&lt;p&gt;I want to write a post about Jekyll itself. Then I may need to include some Liquid statement. Refer to &lt;a href=&quot;http://blog.slaks.net/2013-06-09/writing-about-jekyll-in-jekyll/&quot;&gt;Writing about Jekyll in Jekyll&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Basically:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;put your Liquid statement between  {% raw %}  and {% endraw %}.&lt;/li&gt;
  &lt;li&gt;use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;#123;&lt;/code&gt; to replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt;. HTML recoginzes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;#123;&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{&lt;/code&gt;, while Liquid does not recognize it. This way is limited in that it only viable for html code.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;syntax&quot;&gt;Syntax&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://daringfireball.net/projects/markdown/&quot;&gt;Markdown&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://redcloth.org/textile&quot;&gt;Textile&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;Contents above were inserted mannually.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Cum sociis natoque penatibus et magnis &lt;a href=&quot;#&quot;&gt;dis parturient montes&lt;/a&gt;, nascetur ridiculus mus. &lt;em&gt;Aenean eu leo quam.&lt;/em&gt; Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras mattis consectetur purus sit amet fermentum.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Curabitur blandit tempus porttitor. Nullam quis risus eget urna mollis ornare vel eu leo. Nullam id dolor id nibh ultricies vehicula ut id elit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Etiam porta &lt;strong&gt;sem malesuada magna&lt;/strong&gt; mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.&lt;/p&gt;

&lt;h2 id=&quot;inline-html-elements&quot;&gt;Inline HTML elements&lt;/h2&gt;

&lt;p&gt;HTML defines a long list of available inline tags, a complete list of which can be found on the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element&quot;&gt;Mozilla Developer Network&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;To bold text&lt;/strong&gt;, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;strong&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;To italicize text&lt;/em&gt;, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;em&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Abbreviations, like &lt;abbr title=&quot;HyperText Markup Langage&quot;&gt;HTML&lt;/abbr&gt; should use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt;, with an optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;title&lt;/code&gt; attribute for the full phrase.&lt;/li&gt;
  &lt;li&gt;Citations, like &lt;cite&gt;— Mark otto&lt;/cite&gt;, should use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;cite&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;del&gt;Deleted&lt;/del&gt; text should use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;del&amp;gt;&lt;/code&gt; and &lt;ins&gt;inserted&lt;/ins&gt; text should use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;ins&amp;gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Superscript &lt;sup&gt;text&lt;/sup&gt; uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sup&amp;gt;&lt;/code&gt; and subscript &lt;sub&gt;text&lt;/sub&gt; uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;sub&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of these elements are styled by browsers with few modifications on our part.&lt;/p&gt;

&lt;h2 id=&quot;heading&quot;&gt;Heading&lt;/h2&gt;

&lt;p&gt;Vivamus sagittis lacus vel augue rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.&lt;/p&gt;

&lt;h3 id=&quot;code&quot;&gt;Code&lt;/h3&gt;

&lt;p&gt;Cum sociis natoque penatibus et magnis dis &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code element&lt;/code&gt; montes, nascetur ridiculus mus.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c1&quot;&gt;// Example can be run directly in your JavaScript console&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Create a function that takes two arguments and returns the sum of those arguments&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;adder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;return a + b&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Call the function&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;adder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// &amp;gt; 8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.&lt;/p&gt;

&lt;h3 id=&quot;lists&quot;&gt;Lists&lt;/h3&gt;

&lt;p&gt;Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Praesent commodo cursus magna, vel scelerisque nisl consectetur et.&lt;/li&gt;
  &lt;li&gt;Donec id elit non mi porta gravida at eget metus.&lt;/li&gt;
  &lt;li&gt;Nulla vitae elit libero, a pharetra augue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Vestibulum id ligula porta felis euismod semper.&lt;/li&gt;
  &lt;li&gt;Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.&lt;/li&gt;
  &lt;li&gt;Maecenas sed diam eget risus varius blandit sit amet non magna.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dl&amp;gt;&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;description list element&lt;/code&gt; encloses a list of paris of terms and descriptions. Common uses for this element are to implement a glossary or to display metadata (a list of key-value pairs).&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;HyperText Markup Language (HTML)&lt;/dt&gt;
  &lt;dd&gt;The language used to describe and define the content of a Web page&lt;/dd&gt;

  &lt;dt&gt;Cascading Style Sheets (CSS)&lt;/dt&gt;
  &lt;dd&gt;Used to describe the appearance of Web content&lt;/dd&gt;

  &lt;dt&gt;JavaScript (JS)&lt;/dt&gt;
  &lt;dd&gt;The programming language used to build advanced Web sites and applications&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Nullam quis risus eget urna mollis ornare vel eu leo.&lt;/p&gt;

&lt;h3 id=&quot;tables&quot;&gt;Tables&lt;/h3&gt;

&lt;p&gt;Aenean lacinia bibendum nulla sed consectetur. Lorem ipsum dolor sit amet, consectetur adipiscing elit.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Upvotes&lt;/th&gt;
      &lt;th&gt;Downvotes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tfoot&gt;
    &lt;tr&gt;
      &lt;td&gt;Totals&lt;/td&gt;
      &lt;td&gt;21&lt;/td&gt;
      &lt;td&gt;23&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tfoot&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Alice&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;11&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Bob&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Charlie&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Nullam id dolor id nibh ultricies vehicula ut id elit. Sed posuere consectetur est at lobortis. Nullam quis risus eget urna mollis ornare vel eu leo.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://daringfireball.net/projects/markdown/syntax&quot; title=&quot;Markdown&quot;&gt;The original Markdown tutorial.&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>What's Jekyll?</title>
   <link href="/2013/12/31/whats-jekyll/"/>
   <updated>2013-12-31T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2013/12/31/whats-jekyll</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; is a static site generator, an open-source tool for creating simple yet powerful websites of all shapes and sizes. From &lt;a href=&quot;https://github.com/mojombo/jekyll/blob/master/README.markdown&quot;&gt;the project&apos;s readme&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Jekyll is a simple, blog aware, static site generator. It takes a template directory […] and spits out a complete, static website suitable for serving with Apache or your favorite web server. This is also the engine behind GitHub Pages, which you can use to host your project’s page or blog right here from GitHub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It&apos;s an immensely useful tool and one we encourage you to use here with Hyde.&lt;/p&gt;

&lt;p&gt;Find out more by &lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;visiting the project on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hello, world</title>
   <link href="/2013/11/12/hello-world/"/>
   <updated>2013-11-12T00:00:00+00:00</updated>
   <id>https://www.zhstar.win/2013/11/12/hello-world</id>
   <content type="html">&lt;div class=&quot;message&quot;&gt;
  Hello, world! Welcome your visit.
&lt;/div&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hello, world!&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
 </entry>
 

</feed>
