<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: CJ</title>
    <description>The latest articles on Forem by CJ (@chuanjin).</description>
    <link>https://forem.com/chuanjin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F374774%2F55482506-6c41-494f-ba66-c92197224d02.png</url>
      <title>Forem: CJ</title>
      <link>https://forem.com/chuanjin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/chuanjin"/>
    <language>en</language>
    <item>
      <title>LGTM != Production Ready: Why your CI pipeline is missing the most important step</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Wed, 04 Feb 2026 22:18:34 +0000</pubDate>
      <link>https://forem.com/chuanjin/lgtm-production-ready-why-your-ci-pipeline-is-missing-the-most-important-step-1kok</link>
      <guid>https://forem.com/chuanjin/lgtm-production-ready-why-your-ci-pipeline-is-missing-the-most-important-step-1kok</guid>
      <description>&lt;p&gt;We have linters for syntax and scanners for security. It’s time we started linting for "will this wake me up at 3 AM?"&lt;/p&gt;

&lt;p&gt;We have all been there.&lt;/p&gt;

&lt;p&gt;You submit a Pull Request. The CI passes green. Your colleagues review it and comment "LGTM!" The code is merged and deployed.&lt;/p&gt;

&lt;p&gt;Three days later, at 3:17 AM, PagerDuty fires.&lt;/p&gt;

&lt;p&gt;The root cause wasn't a syntax error. It wasn't a logic bug that unit tests could catch. It was something subtle: an HTTP client missing a timeout setting that caused a cascading failure when a downstream service hiccuped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Senior Intuition" Gap&lt;/strong&gt;&lt;br&gt;
Why did the PR review miss that missing timeout?&lt;/p&gt;

&lt;p&gt;Because standard code reviews usually focus on code style, logic correctness, and maintainability. Standard static analysis tools catch syntax errors or obvious security flaws.&lt;/p&gt;

&lt;p&gt;But nobody is actively grepping for operational maturity.&lt;/p&gt;

&lt;p&gt;Usually, catching these latent failure modes relies on "senior engineer intuition." It's that Spidey-Sense that a battle-hardened SRE develops after years of being woken up on-call. They glance at code and immediately think: “Where is the backoff retry logic here?” or “This unchecked environment variable is going to brick boot-up one day.”&lt;/p&gt;

&lt;p&gt;The problem is that senior intuition doesn't scale. You can't clone your best SRE to review every PR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Failure of Checklists&lt;/strong&gt;&lt;br&gt;
Many organizations try to solve this with the dreaded "Production Readiness Checklist" — a dusty Confluence page with 50 questions like "Have you considered failure domains?"&lt;/p&gt;

&lt;p&gt;Let’s be honest: nobody uses these. They are manual, tedious, done at the very end of the development lifecycle (too late to change architecture), and are usually just "checkbox theatre" to appease management.&lt;/p&gt;

&lt;p&gt;If it's not automated, it doesn't exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shifting "Operability" Left&lt;/strong&gt;&lt;br&gt;
We need to treat operational requirements the same way we treat code style. If gofmt fails, you can't merge. If your code contains latent operational risks, you shouldn't be able to merge either.&lt;/p&gt;

&lt;p&gt;I wanted a tool that codified that "senior engineer intuition" into something executable. I wanted a scanner that doesn't care about my variable names, but cares deeply about whether my application will survive a partial network outage.&lt;/p&gt;

&lt;p&gt;Since I couldn't find one that fit my needs, I built it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introducing Production-Readiness&lt;/strong&gt;&lt;br&gt;
Production-Readiness is an open-source, opinionated scanner designed to detect operational blind spots before they hit production.&lt;/p&gt;

&lt;p&gt;It’s not a replacement for Prometheus or Datadog. It’s a pre-flight check. It looks for the patterns that look "correct" in code but cause fires in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does it actually catch?&lt;/strong&gt;&lt;br&gt;
Unlike a standard linter, this tool is looking for semantic operational patterns. Here are just a few examples of rules that are difficult to catch with standard regex grep:&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;The "Hanging Client" Trap&lt;/strong&gt; It's shockingly easy in many languages to instantiate an HTTP client with infinite timeouts by default.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Risk: A slow downstream dependency ties up all your threads/goroutines, eventually crashing your service.&lt;/li&gt;
&lt;li&gt;The Fix: The scanner flags clients initialized without explicit timeouts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2.&lt;strong&gt;Missing Graceful Shutdown&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Risk: When Kubernetes scales down a pod, it sends a SIGTERM. If your app doesn't catch it and finish in-flight requests, you drop user traffic during every deployment or auto-scale event.&lt;/li&gt;
&lt;li&gt;The Fix: The scanner looks for the presence of signal handling wiring.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3.&lt;strong&gt;Unvalidated Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Risk: Your app ne``eds an API_KEY environment variable to start. You deploy, and it crash-loops because the variable was missing in the new environment.&lt;/li&gt;
&lt;li&gt;The Fix: The scanner checks if critical configuration inputs have validation checks associated with them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Seeing it in Action&lt;/strong&gt;&lt;br&gt;
The tool is written in Go and designed to be a single binary you can drop into any CI pipeline.&lt;/p&gt;

&lt;p&gt;You run it against your source code directory:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ pr scan ./my-microservice&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And it gives you a prioritized report of operational risks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcx9dxnfcggxsonh4y609.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcx9dxnfcggxsonh4y609.png" alt=" " width="580" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
The gap between "code that works" and "code that runs reliably in production" is massive. We need to stop relying on hope and manual checklists to bridge that gap.&lt;/p&gt;

&lt;p&gt;By automating the detection of operational anti-patterns, we can ship faster and, more importantly, sleep better.&lt;/p&gt;

&lt;p&gt;The project is open source and we are just getting started defining the rules of what makes software "production-ready."&lt;/p&gt;

&lt;p&gt;If you've ever been burned by a "silly" configuration mistake in prod, give it a spin.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Star the repo on GitHub&lt;/strong&gt;: &lt;a href="https://github.com/chuanjin/production-readiness" rel="noopener noreferrer"&gt;https://github.com/chuanjin/production-readiness&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>sre</category>
      <category>opensource</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>🚀 Introducing Production Readiness — A Practical Guide to Shipping Software That Survives Reality</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Fri, 02 Jan 2026 16:31:26 +0000</pubDate>
      <link>https://forem.com/chuanjin/introducing-production-readiness-a-practical-guide-to-shipping-software-that-survives-reality-l7b</link>
      <guid>https://forem.com/chuanjin/introducing-production-readiness-a-practical-guide-to-shipping-software-that-survives-reality-l7b</guid>
      <description>&lt;p&gt;Shipping code is easy.&lt;br&gt;
Running it &lt;strong&gt;reliably in production&lt;/strong&gt; is not.&lt;/p&gt;

&lt;p&gt;After years of working as a senior software engineer and tech lead across large enterprises and startups, I’ve repeatedly seen the same pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Systems that work perfectly in development&lt;/li&gt;
&lt;li&gt;MVPs that collapse under real traffic&lt;/li&gt;
&lt;li&gt;Teams reinventing the same production checklists again and again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I decided to turn that experience into an open-source project:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/chuanjin/production-readiness" rel="noopener noreferrer"&gt;Production Readiness&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Production Readiness?
&lt;/h2&gt;

&lt;p&gt;Production Readiness is a curated, opinionated, and practical checklist for engineers who want to ship software that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Observable&lt;/li&gt;
&lt;li&gt;Secure&lt;/li&gt;
&lt;li&gt;Scalable&lt;/li&gt;
&lt;li&gt;Operable&lt;/li&gt;
&lt;li&gt;Maintainable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is &lt;strong&gt;not&lt;/strong&gt; a theoretical document or a vendor pitch.&lt;br&gt;
It is a hands-on guide based on real production incidents, postmortems, and lessons learned the hard way.&lt;/p&gt;

&lt;p&gt;Think of it as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A pre-flight checklist before going live&lt;/li&gt;
&lt;li&gt;A review guide for architecture and DevOps decisions&lt;/li&gt;
&lt;li&gt;A shared vocabulary between developers, SREs, and tech leads&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Project Exists
&lt;/h2&gt;

&lt;p&gt;Most teams focus heavily on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Features&lt;/li&gt;
&lt;li&gt;Velocity&lt;/li&gt;
&lt;li&gt;Frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Far fewer invest early in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Observability&lt;/li&gt;
&lt;li&gt;Failure modes&lt;/li&gt;
&lt;li&gt;Operational ownership&lt;/li&gt;
&lt;li&gt;Security defaults&lt;/li&gt;
&lt;li&gt;Cost awareness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“It worked yesterday. Why is production down?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This repository aims to close that gap by answering questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What must be in place before launch?&lt;/li&gt;
&lt;li&gt;What should be automated vs manual?&lt;/li&gt;
&lt;li&gt;What risks are acceptable at each stage?&lt;/li&gt;
&lt;li&gt;What do experienced teams check instinctively — but never write down?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What’s Inside the Repository?
&lt;/h2&gt;

&lt;p&gt;The project is structured into clear, actionable sections, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architecture &amp;amp; Design Readiness&lt;/li&gt;
&lt;li&gt;Deployment &amp;amp; CI/CD&lt;/li&gt;
&lt;li&gt;Observability (logs, metrics, tracing)&lt;/li&gt;
&lt;li&gt;Security &amp;amp; Access Control&lt;/li&gt;
&lt;li&gt;Reliability &amp;amp; Failure Handling&lt;/li&gt;
&lt;li&gt;Scalability &amp;amp; Performance&lt;/li&gt;
&lt;li&gt;Operations &amp;amp; Incident Response&lt;/li&gt;
&lt;li&gt;Cost &amp;amp; Sustainability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each item is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concrete (not buzzwords)&lt;/li&gt;
&lt;li&gt;Tool-agnostic where possible&lt;/li&gt;
&lt;li&gt;Suitable for startups and mature systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who Is This For?
&lt;/h2&gt;

&lt;p&gt;If you are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A senior engineer reviewing systems before launch&lt;/li&gt;
&lt;li&gt;A tech lead setting engineering standards&lt;/li&gt;
&lt;li&gt;A startup founder shipping your first production system&lt;/li&gt;
&lt;li&gt;A DevOps/SRE tired of repeating the same advice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project is for you.&lt;/p&gt;

&lt;p&gt;Even if you disagree with parts of it — that’s a feature, not a bug. It’s designed to spark discussion and improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source &amp;amp; Community-Driven
&lt;/h2&gt;

&lt;p&gt;This is an open-source project, and I want it to grow with the community.&lt;/p&gt;

&lt;p&gt;You can contribute by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Suggesting missing checklist items&lt;/li&gt;
&lt;li&gt;Sharing real-world lessons learned&lt;/li&gt;
&lt;li&gt;Improving structure or clarity&lt;/li&gt;
&lt;li&gt;Adding examples from different domains (SaaS, IoT, fintech, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⭐ If you find it useful, please consider giving it a star — it helps the project reach more engineers and signals that this kind of practical knowledge matters.&lt;/p&gt;

&lt;p&gt;👉 Repository: &lt;a href="https://github.com/chuanjin/production-readiness" rel="noopener noreferrer"&gt;https://github.com/chuanjin/production-readiness&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Production readiness is not a checkbox you tick at the end.&lt;br&gt;
It’s a mindset you build into how you design, develop, and operate software.&lt;/p&gt;

&lt;p&gt;My hope is that this project helps teams:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fail less catastrophically&lt;/li&gt;
&lt;li&gt;Sleep better after deployments&lt;/li&gt;
&lt;li&gt;Spend more time building value instead of firefighting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If that resonates with you, I’d love your feedback — and your star ⭐.&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>opensource</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Connect Django to PostgreSQL in Docker</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Sat, 23 May 2020 12:04:28 +0000</pubDate>
      <link>https://forem.com/chuanjin/connect-django-to-postgresql-in-docker-34cp</link>
      <guid>https://forem.com/chuanjin/connect-django-to-postgresql-in-docker-34cp</guid>
      <description>&lt;p&gt;Django uses SQLite database by default, now we want to switch it to postgreSQL. Firstly, we fetch postgreSQL docker image and start an instance&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull postgres
docker run --name my-postgres -v /tmp/my-pgdata:/var/lib/postgresql/data -e POSTGRES_PASSWORD=my-password -p 127.0.0.1:5432:5432 -d postgres
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The docker instance name can be whatever you want, here it's named my-postgres for instance, and we mount a volume (e.g &lt;em&gt;/tmp/my-pgdata&lt;/em&gt;) to our container, so that the database files are easier to access for other tools or applications on our host system. And remember to forward the default postgreSQL port and use &lt;code&gt;-d&lt;/code&gt; to put it to background. Next, we install postgreSQL command line client if you haven't done that yet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install postgresql-client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, we connect to postgreSQL, either command below should work, &lt;code&gt;postgres&lt;/code&gt; is the default database and user name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psql postgresql://postgres:my-password@127.0.0.1:5432/postgres
docker exec -it my-postgres psql postgresql://postgres:my-password@127.0.0.1:5432/postgres
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If everything goes as expected, we should be able to connect and list the databases&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~ ❯ docker exec -it my-postgres psql postgresql://postgres:my-password@127.0.0.1:5432/postgres
psql (12.3 (Debian 12.3-1.pgdg100+1))
Type "help" for help.

postgres=# \l
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
-----------+----------+----------+------------+------------+-----------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
(3 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After it's up and running, we install the postgreSQL adapter &lt;code&gt;psycopg2&lt;/code&gt; to our Django project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install psycopg2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Modify &lt;code&gt;settings.py&lt;/code&gt; in the project to use Postgres instead&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;. . .

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'postgres',
        'USER': 'postgres',
        'PASSWORD': 'my-password',
        'HOST': '127.0.0.1',
        'PORT': '5432'
    }
}

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



&lt;p&gt;Now, we are ready to go&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's switch to the database, we can see the default tables are created by Django, cheers!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgres=# \c postgres
You are now connected to database "postgres" as user "postgres".
postgres=# \dt
                   List of relations
 Schema |            Name            | Type  |  Owner
--------+----------------------------+-------+----------
 public | account_emailaddress       | table | postgres
 public | account_emailconfirmation  | table | postgres
 public | auth_group                 | table | postgres
 public | auth_group_permissions     | table | postgres
 public | auth_permission            | table | postgres
 public | auth_user                  | table | postgres
 public | auth_user_groups           | table | postgres
 public | auth_user_user_permissions | table | postgres
 public | authtoken_token            | table | postgres
 public | django_admin_log           | table | postgres
 public | django_content_type        | table | postgres
 public | django_migrations          | table | postgres
 public | django_session             | table | postgres
 public | django_site                | table | postgres
(18 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>django</category>
      <category>postgres</category>
      <category>docker</category>
    </item>
    <item>
      <title>Let's deploy now</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Wed, 13 May 2020 21:38:00 +0000</pubDate>
      <link>https://forem.com/chuanjin/let-s-deploy-now-f9</link>
      <guid>https://forem.com/chuanjin/let-s-deploy-now-f9</guid>
      <description>&lt;p&gt;Previously, we have &lt;a href="https://dev.to/chuanjin/setup-my-blog-using-hexo-h44"&gt;Setup the blog using Hexo&lt;/a&gt; and &lt;a href="https://dev.to/chuanjin/set-up-websites-using-github-pages-4a57"&gt;deploy it to Github page&lt;/a&gt;. Additionally, we can deploy it to &lt;a href="https://vercel.com"&gt;Vercel&lt;/a&gt;(formerly zeit). We can either go to their website to connect it to our Github, Gitlab, etc, or install command line interface and deploy with one hit.&lt;br&gt;
&lt;code&gt;npm i -g vercel&lt;/code&gt;&lt;br&gt;
Just run &lt;code&gt;vercel&lt;/code&gt; or &lt;code&gt;vc&lt;/code&gt; inside the project, it will guide you to setup for the first time and deploy automatically. Note, the command was used to be called &lt;code&gt;now&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/1ZtXNBw-oYo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
    </item>
    <item>
      <title>Bring fortune to your Linux terminal with cowsay figlet lolcat</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Fri, 08 May 2020 21:07:41 +0000</pubDate>
      <link>https://forem.com/chuanjin/bring-fortune-to-your-linux-terminal-with-cowsay-figlet-lolcat-17a9</link>
      <guid>https://forem.com/chuanjin/bring-fortune-to-your-linux-terminal-with-cowsay-figlet-lolcat-17a9</guid>
      <description>&lt;p&gt;We will cover a few interesting commands today, they are &lt;code&gt;figlet&lt;/code&gt; &lt;code&gt;toilet&lt;/code&gt; &lt;code&gt;lolcat&lt;/code&gt; &lt;code&gt;fortune&lt;/code&gt; &lt;code&gt;cowsay&lt;/code&gt; &lt;code&gt;shuf&lt;/code&gt;. To learn a new command, I believe the best way is always to check &lt;code&gt;tldr&lt;/code&gt; for the basic usage and then play with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MMv7V5QP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/figlet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MMv7V5QP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/figlet.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5kaj5sv3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/toilet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5kaj5sv3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/toilet.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Rv0Lk927--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/lolcat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rv0Lk927--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/lolcat.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sSsR8jZs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/fortune.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sSsR8jZs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/fortune.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B-9UUCb8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/cowsay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B-9UUCb8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/cowsay.png" alt=""&gt;&lt;/a&gt;&lt;br&gt;
Not only &lt;em&gt;cow&lt;/em&gt; and &lt;em&gt;dragon&lt;/em&gt;, but also many other options are available to choose. Check them with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls /usr/share/cowsay/cows
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To pick one randomly, &lt;code&gt;shuf&lt;/code&gt; comes in. And to fetch only file name without extension, there're more than one way to do so.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dmfDVQO---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/shuf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dmfDVQO---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/shuf.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, time to put them all together, and try to run it a few more times to see the results.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JnStPdyo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/together.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JnStPdyo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/together.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/b30SXMhuyqo"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Enjoy and have fun\!" | lolcat -a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>linux</category>
    </item>
    <item>
      <title>Learn AWK by examples</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Thu, 07 May 2020 18:49:15 +0000</pubDate>
      <link>https://forem.com/chuanjin/learn-awk-by-examples-580b</link>
      <guid>https://forem.com/chuanjin/learn-awk-by-examples-580b</guid>
      <description>&lt;p&gt;Practise makes perfect.&lt;br&gt;
Good code and examples are usually self-explanatory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.chuanjin.me%2Fimages%2Fawk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.chuanjin.me%2Fimages%2Fawk.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.chuanjin.me%2Fimages%2Fawk-basic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.chuanjin.me%2Fimages%2Fawk-basic.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.chuanjin.me%2Fimages%2Fawk-more.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.chuanjin.me%2Fimages%2Fawk-more.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check &lt;code&gt;man&lt;/code&gt; or GNU online &lt;a href="https://www.gnu.org/software/gawk/manual/html_node/" rel="noopener noreferrer"&gt;guide&lt;/a&gt; to get more information.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>awk</category>
    </item>
    <item>
      <title>Alternatives of man in Linux command line</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Fri, 01 May 2020 20:46:11 +0000</pubDate>
      <link>https://forem.com/chuanjin/alternatives-of-man-in-linux-command-line-1mi8</link>
      <guid>https://forem.com/chuanjin/alternatives-of-man-in-linux-command-line-1mi8</guid>
      <description>&lt;p&gt;When we need help in Linux command line, &lt;code&gt;man&lt;/code&gt; is usually the first friend we check for more information. But it became my second line support after I met other alternatives, e.g. &lt;code&gt;tldr&lt;/code&gt;, &lt;code&gt;cheat&lt;/code&gt; and &lt;code&gt;eg&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  tldr
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/tldr-pages/tldr"&gt;tldr&lt;/a&gt; stands for &lt;strong&gt;too long didn't read&lt;/strong&gt;, it is a simplified and community-driven man pages. Maybe we forget the arguments to a command, or just not patient enough to read the long &lt;code&gt;man&lt;/code&gt; document, here &lt;code&gt;tldr&lt;/code&gt; comes in, it will provide concise information with examples. And I even contributed a couple of lines code myself to help a little bit with the project on Github. It is very easy to install: &lt;code&gt;npm install -g tldr&lt;/code&gt;, and there are many clients available to pick to be able to access the &lt;code&gt;tldr&lt;/code&gt; pages. E.g. install Python client with &lt;code&gt;pip install tldr&lt;/code&gt;, &lt;/p&gt;

&lt;p&gt;To display help information, run &lt;code&gt;tldr -h&lt;/code&gt; or &lt;code&gt;tldr tldr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Take &lt;code&gt;curl&lt;/code&gt; as an example&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aDAhMXH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/tldr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aDAhMXH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/tldr.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  tldr++
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/isacikgoz/tldr"&gt;tldr++&lt;/a&gt; is an interactive tldr client written with go, I just steal the gif from its official site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--46uIL2Ao--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.chuanjin.me/images/tldrpp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--46uIL2Ao--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.chuanjin.me/images/tldrpp.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  cheat
&lt;/h1&gt;

&lt;p&gt;Similarly, &lt;a href="https://github.com/cheat/cheat"&gt;cheat&lt;/a&gt; allows you to create and view interactive cheatsheets on the command-line. It was designed to help remind *nix system administrators of options for commands that they use frequently, but not frequently enough to remember. It is written in Golang, so just download the binary and add it into your &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CTO0J9aq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/cheat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CTO0J9aq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/cheat.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  eg
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/srsudar/eg"&gt;eg&lt;/a&gt; provides useful examples with explanations on the command line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dc6d04jZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dc6d04jZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/eg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I consult &lt;code&gt;tldr&lt;/code&gt;, &lt;code&gt;cheat&lt;/code&gt; or &lt;code&gt;eg&lt;/code&gt; before I ask &lt;code&gt;man&lt;/code&gt; and Google.&lt;/p&gt;

</description>
      <category>linux</category>
    </item>
    <item>
      <title>Capture Network Packet</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Tue, 28 Apr 2020 15:21:17 +0000</pubDate>
      <link>https://forem.com/chuanjin/capture-network-packet-1fp0</link>
      <guid>https://forem.com/chuanjin/capture-network-packet-1fp0</guid>
      <description>&lt;p&gt;Tcpdump is a very useful tool to capture network packets.&lt;br&gt;
e.g. to capture TCP packet from interface lo0 via port 9999&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo tcpdump -i lo0 port 9999 -XX -v
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Here demostrate sending some UDP packets, using tcpdump to capture them and using Tcpreplay to playback.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Send some UDP packets via port 9999
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IlSfDNPG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/udps.png" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;Listen UDP packets from port 9999
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dj-DhdO_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/udpl.png" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;Capture UDP packet using Tcpdump, save captured packets into a file
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pYdVImyh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/tcpdump_udp.png" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;Playback captured packets
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ymVuDSAB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/tcpreplay_udp.png" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;Listen UDP packets to verify
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nJvFg4p_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/udpl2.png" alt=""&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's have more fun! Assuming we have captured some UDP packets using the command below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo tcpdump -i en0 udp port 3333 -XX -v -w li.pcap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then we use tcprewrite command to reverse the source and destination.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VJyEsOWZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/final.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VJyEsOWZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/final.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if we double check the modified .pcap file, it shows as we want.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B9qkJvhV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/reversed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B9qkJvhV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/reversed.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also wrote a shell script to rewrite the network package automatically.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://xmodulo.com/how-to-capture-and-replay-network-traffic-on-linux.html"&gt;http://xmodulo.com/how-to-capture-and-replay-network-traffic-on-linux.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rationallyparanoid.com/articles/tcpdump.html"&gt;http://rationallyparanoid.com/articles/tcpdump.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://danielmiessler.com/study/tcpdump/#gs.Xztynp0"&gt;https://danielmiessler.com/study/tcpdump/#gs.Xztynp0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jianshu.com/p/5334025cfb5e"&gt;http://www.jianshu.com/p/5334025cfb5e&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>bash</category>
      <category>linux</category>
      <category>network</category>
      <category>tcp</category>
    </item>
    <item>
      <title>AQI</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Tue, 28 Apr 2020 14:11:23 +0000</pubDate>
      <link>https://forem.com/chuanjin/aqi-4io4</link>
      <guid>https://forem.com/chuanjin/aqi-4io4</guid>
      <description>&lt;h1&gt;
  
  
  Air Quality Index
&lt;/h1&gt;

&lt;p&gt;I'v been experimenting to fetch data related to &lt;a href="https://en.wikipedia.org/wiki/Air_quality_index"&gt;AQI&lt;/a&gt; in China recently.&lt;/p&gt;

&lt;p&gt;A good resource is &lt;a href="http://aqicn.org"&gt;http://aqicn.org&lt;/a&gt;, which provides air pollution data in a good way by city, and I try to write a python script to crawl the data from it.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Another website is &lt;a href="http://www.stateair.net/"&gt;http://www.stateair.net/&lt;/a&gt;, it reports AQI from US consulate in Chinese major cities, i.e. Beijing, Shanghai, Guangzhou, Chengdu and Shenyang. Similarly, the code to fetch data from it shown below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Both of the code above are using Python and handy packages like &lt;a href="http://docs.python-requests.org/en/master/"&gt;requests&lt;/a&gt; and  &lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/"&gt;Beautiful Soup&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The stateair website also provides historical data for download in CSV format, therefore I use those data to create a simple visulization page. Check it from &lt;a href="https://chuanjin.github.io/pm25/"&gt;https://chuanjin.github.io/pm25/&lt;/a&gt; and source code is availabe from Github &lt;a href="https://github.com/chuanjin/pm25"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Last but not least, I found &lt;a href="http://pm25.in/"&gt;pm25.in&lt;/a&gt; website, and they provide real time data for all Chinese cities, even better, they have opened their API for develper and I also created a Python library based on their API. Code available from &lt;a href="https://github.com/chuanjin/python-aqi-zh"&gt;https://github.com/chuanjin/python-aqi-zh&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>New Vim Hack</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Tue, 28 Apr 2020 13:55:00 +0000</pubDate>
      <link>https://forem.com/chuanjin/new-vim-hack-4l52</link>
      <guid>https://forem.com/chuanjin/new-vim-hack-4l52</guid>
      <description>&lt;p&gt;Previously I am using &lt;a href="https://github.com/spf13/spf13-vim"&gt;spf13&lt;/a&gt; for my vim configuration. However it is a bit sluggish for me since it includes too much settings and plugins which might not be needed for my daily usage, therefore I deicide to move to this &lt;a href="https://github.com/amix/vimrc"&gt;vimrc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;New plugins installed manually such as vim-rails, vim-autoformat, YouCompleteMe, tagbar, vim-ctrlp-tjump etc.&lt;/p&gt;

&lt;p&gt;Ctags is also needed for go to definition.&lt;/p&gt;

&lt;p&gt;I remove/comment out the line to have deafault key mapping for multiple selection in plugins_config.vim &lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let g:multi_cursor_next_key="\&amp;lt;C-s&amp;gt;"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is how it looks for my_configs.vim&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Final look:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QPiyolXp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/new_vim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QPiyolXp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.chuanjin.me/images/new_vim.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vim</category>
      <category>linux</category>
    </item>
    <item>
      <title>Transfer file over TCP/UDP</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Tue, 28 Apr 2020 13:44:18 +0000</pubDate>
      <link>https://forem.com/chuanjin/transfer-file-over-tcp-udp-4o12</link>
      <guid>https://forem.com/chuanjin/transfer-file-over-tcp-udp-4o12</guid>
      <description>&lt;p&gt;This is a small lab I have done to see how easy to use python to transfer file over TCP and UDP. File formats including plain text, MS word, pdf, image and vedio.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>tcp</category>
      <category>udp</category>
      <category>python</category>
    </item>
    <item>
      <title>MQTT security</title>
      <dc:creator>CJ</dc:creator>
      <pubDate>Tue, 28 Apr 2020 13:18:13 +0000</pubDate>
      <link>https://forem.com/chuanjin/secure-mqtt-1ddg</link>
      <guid>https://forem.com/chuanjin/secure-mqtt-1ddg</guid>
      <description>&lt;p&gt;We have covered the &lt;a href="https://www.chuanjin.me/2015/03/19/MQTT/"&gt;MQTT Basics&lt;/a&gt; and &lt;a href="https://www.chuanjin.me/2015/12/07/mqtt-with-websockets/"&gt;MQTT with websockets support&lt;/a&gt;, now we talk about security.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>mqtt</category>
      <category>mosquitto</category>
      <category>security</category>
    </item>
  </channel>
</rss>
