<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>DevOps | 空垠尘</title><link>/en/tags/devops/</link><description>Minimalist Static · Boundless Edge</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>Dukang Xu</managingEditor><webMaster>Dukang Xu</webMaster><copyright>© 2026 空垠尘</copyright><lastBuildDate>Fri, 25 Sep 2026 16:00:00 +0800</lastBuildDate><atom:link href="/en/tags/devops/index.xml" rel="self" type="application/rss+xml"/><item><title>DevOps Troubleshooting and Debugging Playbook</title><link>/en/linux-troubleshooting/</link><pubDate>Fri, 25 Sep 2026 16:00:00 +0800</pubDate><author>Dukang Xu</author><guid isPermaLink="true">/en/linux-troubleshooting/</guid><description>A hands-on diagnostic guide tackling the most notorious production issues: Too Many Open Files limits, phantom full disks, inode exhaustion, zombie processes, Linux OOM killers, and clock skew.</description><content:encoded><![CDATA[<h2 id="introduction-a-systematic-mindset-for-devops-debugging">Introduction: A Systematic Mindset for DevOps Debugging</h2>
<p>In Linux and macOS operations, weird system glitches inevitably emerge:</p>
<ul>
<li>The disk shows gigabytes of free space, yet writes fail with <code>No space left on device</code>.</li>
<li>A port is locked, but no listening process is found.</li>
<li>Containers or backend services vanish silently without application crash logs.</li>
<li>Sudden connection spikes crash systems with <code>Too many open files</code>.</li>
</ul>
<p>Effective troubleshooting is a <strong>systematic deductive process</strong>. This playbook collects 6 high-impact real-world issues with battle-tested root-cause fixes.</p>
<pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">flowchart TD
    Issue[&#34;System Anomalies &amp; Alerts&#34;] --&gt; A[&#34;1. File Descriptor Limits&lt;br/&gt;(Too Many Open Files)&#34;]
    Issue --&gt; B[&#34;2. Phantom Full Disks&lt;br/&gt;(Inode Exhaustion / Unreleased FD)&#34;]
    Issue --&gt; C[&#34;3. Port Clashes &amp; Zombies&lt;br/&gt;(Address in use / Defunct)&#34;]
    Issue --&gt; D[&#34;4. Silent Process Termination&lt;br/&gt;(Kernel OOM Killer)&#34;]
    Issue --&gt; E[&#34;5. Clock Skew &amp; Auth Failures&lt;br/&gt;(NTP Synchronization)&#34;]
    Issue --&gt; F[&#34;6. macOS Dev Bottlenecks&lt;br/&gt;(Homebrew Mirroring &amp; Network)&#34;]
</code></pre><hr>
<h2 id="1-resolving-too-many-open-files-descriptor-exhaustion">1. Resolving <code>Too Many Open Files</code> (Descriptor Exhaustion)</h2>
<p>In Unix, &ldquo;everything is a file&rdquo; (sockets, pipes, disk files). When concurrent connections exceed system thresholds, the OS denies new descriptors.</p>
<h3 id="1-permanent-linux-production-tuning">1. Permanent Linux Production Tuning</h3>
<p>Running <code>ulimit -n 65535</code> only affects the active terminal session. Make it permanent:</p>
<h4 id="-modify-system-limits-etcsecuritylimitsconf">① Modify System Limits (<code>/etc/security/limits.conf</code>)</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">* soft nofile 655350
</span></span><span class="line"><span class="ln">2</span><span class="cl">* hard nofile 655350
</span></span><span class="line"><span class="ln">3</span><span class="cl">root soft nofile 655350
</span></span><span class="line"><span class="ln">4</span><span class="cl">root hard nofile 655350
</span></span></code></pre></div><h4 id="-modify-systemd-global-daemon-limits-etcsystemdsystemconf">② Modify Systemd Global Daemon Limits (<code>/etc/systemd/system.conf</code>)</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="ln">1</span><span class="cl"><span class="k">[Manager]</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="na">DefaultLimitNOFILE</span><span class="o">=</span><span class="s">655350</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="na">DefaultLimitNPROC</span><span class="o">=</span><span class="s">655350</span>
</span></span></code></pre></div><h4 id="-check-open-descriptors-by-process">③ Check Open Descriptors by Process</h4>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">ls /proc/&lt;PID&gt;/fd <span class="p">|</span> wc -l
</span></span></code></pre></div><h3 id="2-macos-developer-environment-tuning">2. macOS Developer Environment Tuning</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Check current limit</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">launchctl limit maxfiles
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># Temporarily raise limit for active terminal</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">sudo launchctl limit maxfiles <span class="m">65536</span> <span class="m">200000</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="nb">ulimit</span> -n <span class="m">65536</span>
</span></span></code></pre></div><hr>
<h2 id="2-phantom-full-disks--inode-exhaustion-no-space-left-on-device">2. Phantom Full Disks &amp; Inode Exhaustion (<code>No space left on device</code>)</h2>
<pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">sequenceDiagram
    autonumber
    participant App as Application (Nginx / Java)
    participant Disk as Disk File (/var/log/app.log)
    participant Admin as DevOps Engineer

    App-&gt;&gt;Disk: Writes heavy logs (Holds open FD)
    Admin-&gt;&gt;Disk: rm /var/log/app.log (Removes directory entry)
    Note over Disk: Space NOT freed! Open FD still referenced
    Admin-&gt;&gt;App: Locates unreleased FD (lsof | grep deleted) &amp; truncates
    Note over Disk: Disk space reclaimed immediately!
</code></pre><h3 id="case-a-file-deleted-by-rm-but-process-holds-open-descriptor">Case A: File Deleted by <code>rm</code>, but Process Holds Open Descriptor</h3>
<p>When a large log file is removed while an application is actively writing to it, Linux unlinks the directory name, but disk blocks <strong>remain allocated</strong> until the process releases the descriptor.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. Find deleted files held by active processes</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo lsof <span class="p">|</span> grep -i deleted
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. Free space gracefully without restarting the service</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">sudo truncate -s <span class="m">0</span> /proc/&lt;PID&gt;/fd/&lt;FD&gt;
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># Or reload the service: sudo systemctl reload nginx</span>
</span></span></code></pre></div><h3 id="case-b-available-space-but-exhausted-inodes">Case B: Available Space but Exhausted Inodes</h3>
<p>Millions of tiny cache or session files can consume all filesystem inodes:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. Check inode utilization</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">df -i
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. Count directories containing the highest number of files</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">find /var/spool/ -type d -exec sh -c <span class="s2">&#34;echo -n &#39;{}: &#39;; ls -1 &#39;{}&#39; | wc -l&#34;</span> <span class="se">\;</span> <span class="p">|</span> sort -n -k <span class="m">2</span>
</span></span></code></pre></div><hr>
<h2 id="3-port-conflicts--zombie-process-cleanup">3. Port Conflicts &amp; Zombie Process Cleanup</h2>
<h3 id="1-instant-port-identification--termination">1. Instant Port Identification &amp; Termination</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Locate process on port 8080</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo lsof -i :8080
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># Or</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">sudo ss -tulnp <span class="p">|</span> grep :8080
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># Instantly kill whatever is holding the port</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">sudo fuser -k 8080/tcp
</span></span></code></pre></div><h3 id="2-diagnosing-zombie-processes-z--defunct">2. Diagnosing Zombie Processes (<code>Z</code> / Defunct)</h3>
<p>Zombie processes are already dead, so <code>kill -9 &lt;ZOMBIE_PID&gt;</code> does nothing. You must target the <strong>Parent Process (PPID)</strong>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. List zombie processes</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">ps aux <span class="p">|</span> grep <span class="s1">&#39;Z&#39;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. Find the Parent PID (PPID)</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">ps -o <span class="nv">ppid</span><span class="o">=</span> -p &lt;ZOMBIE_PID&gt;
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 3. Reload or terminate the parent to let systemd (PID 1) reap the zombie</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">sudo <span class="nb">kill</span> -HUP &lt;PARENT_PID&gt;
</span></span></code></pre></div><hr>
<h2 id="4-silent-process-termination-linux-kernel-oom-killer">4. Silent Process Termination: Linux Kernel OOM Killer</h2>
<p>When system memory runs out, the Linux kernel invokes the <strong>Out of Memory (OOM) Killer</strong> to terminate resource-heavy processes.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Check kernel ring buffer for OOM events</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo dmesg -T <span class="p">|</span> grep -i -E <span class="s2">&#34;oom|out of memory|killed process&#34;</span>
</span></span></code></pre></div><p><strong>Remediation</strong>:</p>
<ol>
<li><strong>Add Swap Space</strong> (vital for 1–2GB cloud instances &amp; Raspberry Pis):
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo fallocate -l 2G /swapfile
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo chmod <span class="m">600</span> /swapfile
</span></span><span class="line"><span class="ln">3</span><span class="cl">sudo mkswap /swapfile
</span></span><span class="line"><span class="ln">4</span><span class="cl">sudo swapon /swapfile
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;/swapfile none swap sw 0 0&#39;</span> <span class="p">|</span> sudo tee -a /etc/fstab
</span></span></code></pre></div></li>
<li><strong>Configure Memory Limits in Docker / Kubernetes</strong>.</li>
</ol>
<hr>
<h2 id="5-clock-skew-causing-tls--authentication-failures">5. Clock Skew Causing TLS &amp; Authentication Failures</h2>
<p>If system time drifts, HTTPS certificates fail verification and S3/JWT signatures are rejected.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 1. Inspect time and NTP sync status</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">timedatectl status
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 2. Set timezone and enable automatic NTP synchronization</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">sudo timedatectl set-timezone UTC
</span></span><span class="line"><span class="ln">6</span><span class="cl">sudo timedatectl set-ntp <span class="nb">true</span>
</span></span></code></pre></div><hr>
<h2 id="6-macos-homebrew-mirror-acceleration--reset">6. macOS Homebrew Mirror Acceleration &amp; Reset</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. Switch to fast mirror</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nb">export</span> <span class="nv">HOMEBREW_API_DOMAIN</span><span class="o">=</span><span class="s2">&#34;https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/api&#34;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="nb">export</span> <span class="nv">HOMEBREW_BOTTLE_DOMAIN</span><span class="o">=</span><span class="s2">&#34;https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles&#34;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nb">export</span> <span class="nv">HOMEBREW_BREW_GIT_REMOTE</span><span class="o">=</span><span class="s2">&#34;https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="nb">export</span> <span class="nv">HOMEBREW_CORE_GIT_REMOTE</span><span class="o">=</span><span class="s2">&#34;https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 2. Reset back to official defaults</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nb">unset</span> HOMEBREW_API_DOMAIN
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="nb">unset</span> HOMEBREW_BOTTLE_DOMAIN
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="nb">export</span> <span class="nv">HOMEBREW_BREW_GIT_REMOTE</span><span class="o">=</span><span class="s2">&#34;https://github.com/Homebrew/brew&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nb">export</span> <span class="nv">HOMEBREW_CORE_GIT_REMOTE</span><span class="o">=</span><span class="s2">&#34;https://github.com/Homebrew/homebrew-core&#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">brew update
</span></span></code></pre></div><hr>
<h2 id="conclusion">Conclusion</h2>
<p>Understanding fundamental OS mechanisms transforms troubleshooting from frustrating guesswork into precise, surgical problem-solving.</p>
]]></content:encoded><category>DevOps</category><category>Troubleshooting</category><category>Linux</category><category>macOS</category><category>System Tuning</category><category>Debugging</category></item><item><title>Essential Linux &amp; DevOps Commands Handbook</title><link>/en/linux-commands/</link><pubDate>Thu, 17 Sep 2026 10:00:00 +0800</pubDate><author>Dukang Xu</author><guid isPermaLink="true">/en/linux-commands/</guid><description>A battle-tested handbook summarizing high-frequency commands in modern Linux and DevOps operations: covering SSH key matrices, Crontab pitfalls, symlink mechanics, nsenter container debugging, and modern CLI tools.</description><content:encoded><![CDATA[<h2 id="introduction-why-we-need-a-modern-command-handbook">Introduction: Why We Need a Modern Command Handbook</h2>
<p>The Linux command-line landscape is vast. Developers often resort to copying and pasting commands mechanically, only to get stuck when dealing with edge cases such as multi-host jump setups, stripped-down containers lacking debugging shells, or silent cron job failures.</p>
<p>This handbook is organized around <strong>real-world production scenarios</strong>, condensing essential workflows into 5 high-impact modules.</p>
<pre tabindex="0"><code class="language-mermaid" data-lang="mermaid">graph TD
    Root[&#34;Modern DevOps Command System&#34;]
    
    Root --&gt; A[&#34;1. SSH Matrix &amp; Remote Auth&#34;]
    A --&gt; A1[&#34;Ed25519 Modern Robust Keys&#34;]
    A --&gt; A2[&#34;~/.ssh/config Multi-Host &amp; Jump Hosts&#34;]
    A --&gt; A3[&#34;Local &amp; Dynamic Port Forwarding&#34;]
    
    Root --&gt; B[&#34;2. Scheduled Jobs &amp; Daemons&#34;]
    B --&gt; B1[&#34;Crontab Syntax &amp; Environment Traps&#34;]
    B --&gt; B2[&#34;Supervisord Process Auto-Restart&#34;]
    
    Root --&gt; C[&#34;3. File &amp; Time Management&#34;]
    C --&gt; C1[&#34;ln Symlink Practices &amp; Safe Deletion&#34;]
    C --&gt; C2[&#34;date Formatting &amp; Timestamps&#34;]
    C --&gt; C3[&#34;Disk &amp; RAM Diagnostics (df / du / free)&#34;]
    
    Root --&gt; D[&#34;4. Networking &amp; Namespaces&#34;]
    D --&gt; D1[&#34;lsof &amp; ss Port Identification&#34;]
    D --&gt; D2[&#34;nsenter Container Namespace Entry&#34;]
    
    Root --&gt; E[&#34;5. Modern CLI Toolkit&#34;]
    E --&gt; E1[&#34;ripgrep Blazing Text Search&#34;]
    E --&gt; E2[&#34;fzf Interactive Fuzzy Filtering&#34;]
    E --&gt; E3[&#34;jq Structured JSON Slicing&#34;]
</code></pre><hr>
<h2 id="1-ssh-remote-connections--key-matrices">1. SSH Remote Connections &amp; Key Matrices</h2>
<h3 id="1-modern-ssh-key-generation-ed25519-preferred">1. Modern SSH Key Generation (Ed25519 Preferred)</h3>
<p>Replace legacy RSA 2048/4096 keys with modern <strong>Ed25519</strong> elliptic-curve keys:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Generate ed25519 key pair</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">ssh-keygen -t ed25519 -C <span class="s2">&#34;your_email@example.com&#34;</span> -f ~/.ssh/id_ed25519
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># Distribute public key to remote host for passwordless login</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">ssh-copy-id -i ~/.ssh/id_ed25519.pub user@192.168.1.100
</span></span></code></pre></div><h3 id="2-multi-host-management-with-sshconfig">2. Multi-Host Management with <code>~/.ssh/config</code></h3>
<p>Configure aliases in <code>~/.ssh/config</code> to avoid memorizing raw IPs, ports, and credentials:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl"># Cloud Server
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">Host cloud
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    HostName 1.2.3.4
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    User root
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    Port 2222
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    IdentityFile ~/.ssh/id_ed25519
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"># Local Raspberry Pi
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">Host rpi
</span></span><span class="line"><span class="ln">10</span><span class="cl">    HostName 192.168.1.100
</span></span><span class="line"><span class="ln">11</span><span class="cl">    User pi
</span></span><span class="line"><span class="ln">12</span><span class="cl">    IdentityFile ~/.ssh/id_ed25519
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"># Jump Host to Internal Network
</span></span><span class="line"><span class="ln">15</span><span class="cl">Host internal-db
</span></span><span class="line"><span class="ln">16</span><span class="cl">    HostName 10.0.0.5
</span></span><span class="line"><span class="ln">17</span><span class="cl">    User dbadmin
</span></span><span class="line"><span class="ln">18</span><span class="cl">    ProxyJump cloud
</span></span></code></pre></div><p>Connect instantly with <code>ssh cloud</code> or <code>ssh internal-db</code>.</p>
<h3 id="3-ssh-port-forwarding">3. SSH Port Forwarding</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Local Port Forwarding (-L): Map remote DB (3306) to local 13306</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">ssh -N -L 13306:127.0.0.1:3306 user@remote-server
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># Dynamic SOCKS5 Proxy (-D): Turn remote server into a secure proxy tunnel</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">ssh -N -D <span class="m">10808</span> user@remote-server
</span></span></code></pre></div><hr>
<h2 id="2-cron-jobs--daemon-supervision">2. Cron Jobs &amp; Daemon Supervision</h2>
<h3 id="1-crontab-syntax--critical-pitfalls">1. Crontab Syntax &amp; Critical Pitfalls</h3>
<p>Crontab uses 5 time fields: <code>Minute Hour Day Month Weekday Command</code>.</p>
<blockquote>
<p>⚠️ <strong>Three Major Crontab Pitfalls</strong>:</p>
<ol>
<li><strong>Missing Environment Variables</strong>: Cron runs with a minimal <code>PATH</code>. Always specify <strong>absolute paths</strong> (e.g. <code>/usr/local/bin/python3</code>) or explicitly export <code>PATH</code> in your script.</li>
<li><strong>Working Directory</strong>: Cron executes in the user&rsquo;s home directory by default. Always <code>cd /path/to/workdir</code> inside scripts.</li>
<li><strong>Silent Output Loss</strong>: Always redirect stdout and stderr to a log file:
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="m">0</span> <span class="m">3</span> * * * /usr/bin/bash /opt/backup.sh &gt;&gt; /var/log/backup.log 2&gt;<span class="p">&amp;</span><span class="m">1</span>
</span></span></code></pre></div></li>
</ol>
</blockquote>
<h3 id="2-process-supervision-with-supervisord">2. Process Supervision with Supervisord</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ini" data-lang="ini"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">; /etc/supervisor/conf.d/my-app.conf</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="k">[program:my-app]</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="na">directory</span><span class="o">=</span><span class="s">/opt/my-app</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="na">command</span><span class="o">=</span><span class="s">/usr/bin/python3 app.py</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="na">autostart</span><span class="o">=</span><span class="s">true</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="na">autorestart</span><span class="o">=</span><span class="s">true</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="na">stderr_logfile</span><span class="o">=</span><span class="s">/var/log/my-app.err.log</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="na">stdout_logfile</span><span class="o">=</span><span class="s">/var/log/my-app.out.log</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="na">user</span><span class="o">=</span><span class="s">www-data</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo supervisorctl reread
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo supervisorctl update
</span></span><span class="line"><span class="ln">3</span><span class="cl">sudo supervisorctl status
</span></span></code></pre></div><hr>
<h2 id="3-symlinks--system-timestamps">3. Symlinks &amp; System Timestamps</h2>
<h3 id="1-symbolic-links-ln--s">1. Symbolic Links (<code>ln -s</code>)</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Create symbolic link: ln -s &lt;target_path&gt; &lt;link_name&gt;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">ln -s /mnt/data/music ~/Music
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># Safe deletion: Never include a trailing slash when removing a symlink!</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">rm ~/Music      <span class="c1"># Correct: deletes the link</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">rm -rf ~/Music/ <span class="c1"># Dangerous: might delete real contents in the target directory!</span>
</span></span></code></pre></div><h3 id="2-date-formatting--timestamp-conversion">2. <code>date</code> Formatting &amp; Timestamp Conversion</h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Format current standard time</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">date +<span class="s2">&#34;%Y-%m-%d %H:%M:%S&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># Convert Unix timestamp to human-readable date</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">date -d @1727258400 +<span class="s2">&#34;%Y-%m-%d %H:%M:%S&#34;</span>  <span class="c1"># (Linux)</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">date -r <span class="m">1727258400</span> +<span class="s2">&#34;%Y-%m-%d %H:%M:%S&#34;</span>  <span class="c1"># (macOS)</span>
</span></span></code></pre></div><hr>
<h2 id="4-container-namespace-penetration-nsenter">4. Container Namespace Penetration (<code>nsenter</code>)</h2>
<p>Minimal container images (e.g., Distroless, Alpine) often lack <code>bash</code>, <code>curl</code>, or network debugging utilities. Use <strong><code>nsenter</code></strong> to enter the container&rsquo;s namespaces directly from the host:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. Get container PID on the host</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nv">PID</span><span class="o">=</span><span class="k">$(</span>docker inspect --format <span class="s1">&#39;{{ .State.Pid }}&#39;</span> &lt;container_name_or_id&gt;<span class="k">)</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 2. Enter container network namespace only</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># Use host utilities directly inside the container&#39;s network stack!</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">sudo nsenter -t <span class="nv">$PID</span> -n ss -tulnp
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">sudo nsenter -t <span class="nv">$PID</span> -n tcpdump -i eth0 port <span class="m">80</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 3. Enter all container namespaces</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">sudo nsenter -t <span class="nv">$PID</span> -m -u -i -n -p
</span></span></code></pre></div><hr>
<h2 id="5-modern-cli-toolkit">5. Modern CLI Toolkit</h2>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Task</th>
					<th style="text-align: left">Traditional Tool</th>
					<th style="text-align: left">Modern Alternative</th>
					<th style="text-align: left">Advantage</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong>Code / Text Search</strong></td>
					<td style="text-align: left"><code>grep -r</code></td>
					<td style="text-align: left"><strong><code>rg</code> (ripgrep)</strong></td>
					<td style="text-align: left">Rust-based, multithreaded, respects <code>.gitignore</code></td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Fuzzy Search</strong></td>
					<td style="text-align: left">Paging tools</td>
					<td style="text-align: left"><strong><code>fzf</code></strong></td>
					<td style="text-align: left">Interactive fuzzy matching for files, history, commits</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>JSON Processing</strong></td>
					<td style="text-align: left">Manual parsing</td>
					<td style="text-align: left"><strong><code>jq</code></strong></td>
					<td style="text-align: left">Structured filtering and slice extraction</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Disk Space Analysis</strong></td>
					<td style="text-align: left"><code>du -sh *</code></td>
					<td style="text-align: left"><strong><code>ncdu</code> / <code>dust</code></strong></td>
					<td style="text-align: left">Interactive visual disk usage explorer</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>System Monitoring</strong></td>
					<td style="text-align: left"><code>top</code></td>
					<td style="text-align: left"><strong><code>btop</code> / <code>htop</code></strong></td>
					<td style="text-align: left">Modern dashboard for CPU, RAM, network, and process tree</td>
			</tr>
	</tbody>
</table>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Power One-Liners:</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">rg <span class="s2">&#34;DATABASE_URL&#34;</span> /opt/projects/
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">history</span> <span class="p">|</span> fzf
</span></span><span class="line"><span class="ln">4</span><span class="cl">sudo lsof -i :8080
</span></span></code></pre></div>]]></content:encoded><category>Linux</category><category>DevOps</category><category>CLI</category><category>SSH</category><category>Operations</category><category>Productivity</category></item></channel></rss>