1. Keep learning forward

    To be updated ...
  2. #TIL : How SMTP works

    When a email send through an SMTP (with authentication), every SMTP server is a hop in mail routing. So it will transfer to localmail or forward the email to next hop (shortest distance via DNS MX record).

    And standard port of SMTP is 25 (unsecured, but can upgrade to TLS via STARTTLS command).

    $ nslookup -type=mx gmail.com
    Non-authoritative answer:     
    gmail.com       mail exchanger = 20 alt2.gmail-smtp-in.l.google.com.                                                    
    gmail.com       mail exchanger = 5 gmail-smtp-in.l.google.com.                                                          
    gmail.com       mail exchanger = 30 alt3.gmail-smtp-in.l.google.com.                                                    
    gmail.com       mail exchanger = 10 alt1.gmail-smtp-in.l.google.com.                                                    
    gmail.com       mail exchanger = 40 alt4.gmail-smtp-in.l.google.com.                                                    
    Authoritative answers can be found from:

    So shortest SMTP of gmail.com domain is gmail-smtp-in.l.google.com

    $ telnet gmail-smtp-in.l.google.com 25
  3. #TIL : Send ENTER key to kernel

    When you try to send an Enter keyboard to linux kernel, it looks like nothing happens.

    This is because you only send a key press (KEY DOWN) but don't send an key release (KEY UP) event after that.

  4. #TIL : BASH tracing commands

    Thank Hiro Ishii for teaching me this

    set -x will print all running commands in your bash script

    So I dove in and look for all set options of BASH.

    And this is what I got , http://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html

  5. #TIL : BASH return a value in function

    Creating function is a good way to refactor your bash script. But BASH doesn't support returning a value in true way, so it makes a bit of challenge to handle that.

    You can use this trick

    hello() {
    	echo "Hello $1"
    hw=$(hello "KhanhIceTea")
    echo $hw

    But what if you want to echo log message in hello function, it will be merged to returned value.

    hello() {
    	echo "System is weaking up and brush its teeth :))"
    	echo "Hello $1"
    hw=$(hello "KhanhIceTea")
    echo "This is returned value of hello function :"
    echo $hw

    This is a how to resolve it, forwarding log message to stderr instead of stdout by default

    hello() {
    	echo "System is weaking up and brush its teeth :))" >&2
    	echo "Hello $1"
    hw=$(hello "KhanhIceTea")
    echo "This is returned value of hello function :"
    echo $hw

    Where there is a shell, there is a way !

  6. #TIL : BASH exiting on first error

    Setting a flag set -e to bash script will let the script exit on first error occurs, so if you want to ignore a command just adding || true to suffix

    set -e
    errorCmd $1 || true
    echo "Run here !"

    And opposite of set -e is set +e, haha of course !

    set +e
    errorCmd $1
    echo "Still run here !"
  7. #TIL : Zip compressing list of files

    To specify a list of compressed files when using zip cli tool, you could use -@ [file_list] flag. And file_list is a file contains list of compressed file (new line separated)


    $ zip changed.zip -@ changed_files.txt

    Or use stdin pipe

    $ find . -mmin -60 -print | zip changed_1_hour_ago -@

    This will zip all changed files 1 hour ago

  8. #TIL : Blocking specified country to prevent from DDOS

    Last day I checked system logs and got a lot of warning messages mentioned that my server has been attack via Brute-force. So I decided to blocked some countries from connecting to attacked ports (21, 25). They are China, Russia and US.

    This site provides a list of IP blocks of specified country


  9. #TIL : TCP FIN timeout

    The TCP FIN timeout belays the amount of time a port must be inactive before it can reused for another connection. The default is often 60 seconds, but can normally be safely reduced to 30 or even 15 seconds:

    net.ipv4.tcp_fin_timeout = 15

    Ref : https://www.linode.com/docs/web-servers/nginx/configure-nginx-for-optimized-performance

  10. #TIL : Lock and unlock a user password

    In Linux, you can prevent a user from login by locking it.


    $ sudo passwd -l [user]


    $ sudo passwd -u [user]
  11. #TIL : Generate dhparam file faster

    openssl uses strong prime (which is useless for security but requires an awful lot more computational effort. A "strong prime" is a prime p such that (p-1)/2 is also prime). So it will be faster if we add option -dsaparam to the command

    $ openssl dhparam -dsaparam -out /etc/ssl/private/dhparam.pem 4096

    Ref : https://security.stackexchange.com/a/95184

  12. #TIL : Grep : find a string in folder

    Grep is a greate tool for searching a string in files.


    $ grep -nr '[string]' [folder]

    If you want to show surrounding lines the result, add flag -C [number] to the command

    $ grep -nr -C 3 'hello' src
  13. #TIL : Ansible playbook : skip to task

    You can skip to a task by its name by adding parameter --start-at

    $ ansible-playbook playbook.yml --start-at="[your task name]"
  14. #TIL : Mycli : a new good cli MySql Client

    This tool is written in Python with super cool features (auto-complete and colors).

    Worth a shot !


    $ pip install mycli


    $ mycli -h -P 3306 -u root



  15. #TIL : Enable reverse proxy in CentOS

    CentOS with SELinux enabled by default will block any http proxy connection. So you have to enable this permission.

    Temporary enable

    $ /usr/sbin/setsebool httpd_can_network_connect 1

    Permanent enable

    $ /usr/sbin/setsebool -P httpd_can_network_connect 1
  16. #TIL : Create SSH tunnel manually

    SSH Tunnel is a fast way to transfer traffic through unsafe internet today. It would be used in MySQL connect, FTP connect or HTTP connect, ...

    Syntax :

    $ ssh -L [local_port]:[remote_endpoint]:[remote_port] [ssh_user]:[ssh_ip]

    Example :

    Lets say you have a EC2 instance ( and remote DB instance ( listening port 3306

    $ ssh -L 3307: root@

    Testing ssh tunnel

    $ telnet 3307
    $ # or
    $ mysql -h -P 3307 -u root -p
  17. #TIL : Scope and Closure

    Run this code

    for (var i=1; i<=5; i++) {
    	setTimeout( function timer(){
    		console.log( i );
    	}, i*1000 );

    What you expected


    But, result is


    Solution is

    for (var i = 1; i <= 5; i++) {
        setTimeout((function timer(j) {
            return function() {
        })(i), i * 1000);


    for (var i=1; i<=5; i++) {
    		setTimeout( function timer(){
    			console.log( j );
    		}, j*1000 );
  18. #TIL : Eval function and with block

    JS code will be slower if engine detects any of 'eval' function or 'with' block b/c compiler stop optimizing the code

  19. #TIL : Remap Capslock to Control key

    Edit file /etc/default/keyboard and set


    Then, logout and log in again to impact

  20. #TIL : Ping Google to crawl updated content

    When you post new content to your website, the fastest way is ping search engines to notify them. After that, they will try to crawl and index your page.

    One way to ping search engines is using XMLRPC ping

    This is a example XMLRPC request (HTTP POST request with xml body)


    > POST /ping/RPC2 HTTP/1.1
    > Host: blogsearch.google.com
    > User-Agent: curl/7.47.0
    > Accept: */*
    > content-type: application/xml
    > Content-Length: 239
    <?xml version="1.0" encoding="UTF-8"?>
             <value>Page Title</value>


    < HTTP/1.1 200 OK
    < Content-Type: text/xml; charset=ISO-8859-1
    < X-Content-Type-Options: nosniff
    < Date: Tue, 08 Aug 2017 05:04:01 GMT
    < Server: psfe
    < Cache-Control: private
    < X-XSS-Protection: 1; mode=block
    < X-Frame-Options: SAMEORIGIN
    < Accept-Ranges: none
    < Vary: Accept-Encoding
    < Transfer-Encoding: chunked
    <?xml version="1.0"?>
          <name>message</name><value>Thanks for the ping.</value>

    Popular XML Servers

  21. #TIL : Runing old java applets on brower

    Mostly morden browser has stop support Java plugins, so you can't run Java applet on browser.

    Temporary way :

    • run in IE or Safari
    • run in an old Firefox (version 23)

    And what if old java applet can't be runned on Java 8 because of weak signature algorithm. Try this

    • Open java.security file :
      • In MacOS, located in /Library/Java/JavaVirtualMachines/jdk[jdk-version].jdk/Contents/Home/jre/lib/security
      • In Windows, located in C:\Program File x86\Java\jre\lib\security
    • Comment this line, jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
    • Rerun applet
  22. #TIL : realpath function

    If you pass a non-exists path to function realpath, it returns empty string. So please don't do something like :

    function storage_path($folder) {
    	return realpath(__DIR__.'/storage/'.$folder);

    if you expect it return full path of new folder !

  23. #TIL : Cleaning up old linux kernels

    Last day, I try to reboot a production server which has out-of-space /boot (I upgraded many kernels without rebooting, so system doesn't clean up old ones). And in the end, doom day had come ! It installed new kernel failed and booting to that kernel. My system crashed !

    So, I learned from it :

    • Never ever upgrade kernel without cleaning up old ones (just reboot)
    • Never ever reboot a production without backup
    • MORE IMPORTANT, NEVER do 2 above things at same time in the weekend !!!

    Solution :

    • Check current kernel : uname -r

    • List all kernels : dpkg --list | grep linux-image

    • Remove a kernel : sudo apt-get purge linux-image-x.x.x-x-generic

    • Finally, update grub after removing all old kernels : sudo update-grub2

    • YOLO command for DEBIAN distros (to remove all of old kernels in 1 line), from AskUbuntu

    dpkg --list | grep linux-image | awk '{ print $2 }' | sort -V | sed -n '/'`uname -r`'/q;p' | xargs sudo apt-get -y purge

    THEN, sudo reboot

  24. #TIL : HTTP2 supported for python requests library

    The sophisticated http client in Python is requests, it has simple API but powerful features. You can use it for crawling, sending request to third-party API or writing tests.

    Btw, at this moment it doesn't support HTTP/2 protocol (actually we often doesn't need its Server Push or Multi resource stream features). But sometime the API endpoint only supports HTTP/2 like Akamai Load Balacing service.

    The hero is new library named hyper, it has been developing to support full HTTP/2 specs. But if all we need is requesting single request to a HTTP/2 server. It works like a charm.


    $ pip install requests
    $ pip install hyper


    import requests
    from hyper.contrib import HTTP20Adapter
    s = requests.Session()
    s.mount('https://', HTTP20Adapter())
    r = s.get('https://cloudflare.com/')

    This mean any url has prefix https:// will be hanlded by HTTP20Adaper of hyper library


    If you run above example, you will see the result


    While you expected it would auto-follow redirect to the page https://www.cloudflare.com/

    We can fix it by using the newer version than 0.7.0 to fix the header key bytestring issue

    $ pip uninstall hyper
    $ pip install https://github.com/Lukasa/hyper/archive/development.zip

    Then try it out !!!

  25. #TIL : Free sandbox server for development

    We can use Heroku as a forever-free sandbox solution for testing or hosting micro service. Adding a credit card to have 1000 free computing hours.

    Heroku will make a service down if no received request come. We can use a cronjob-like service to check service health and keep it live !!! ;)

    Cronjob check health SASS : pingdom, statuscake, port-monitor, uptimerobot

    Btw, I don't recommend you keep service live but no use, it makes Heroku infrastructure heavy and THAT'S NOT FAIR for them !

  26. #TIL : Gearman bash worker and client

    Gearman is a awesome job queue service that helps you scale your system. In smaller context, it can help us to run a background woker for minor tasks like backup data, cleaning system.

    Install :

    $ sudo apt install gearman-job-server gearman-tools

    Create a worker bash script


    echo $1
    echo $2

    Run worker, -w means run as worker mode , -f test means function name will be test

    $ chmod +x worker.sh
    $ gearman -w -f test xargs ./worker.sh

    Sending job

    $ gearman -f test "hello" "hogehoge"

    Sending background job

    $ gearman -b -f test "hello" "hogehoge"
  27. #TIL : Resolving conflict like a boss

    When using git merge new branch to old branch, you just want use all ours or theirs version but be lazy to update every conflicted file.

    grep -lr '<<<<<<<' . | xargs git checkout --ours


    grep -lr '<<<<<<<' . | xargs git checkout --theirs

    Explain : these commands will find any file contains <<<<<<< string (conflicted file) and run git checkout --[side]

  28. #TIL : Reducing docker image the right way

    When building an image, Docker engine commit file system layer on every command (RUN, ADD, COPY). So next time you installing packages from package manager likes apt, yum, pacman, ...remember clean their cache in same line.


    RUN apt-get update
    RUN apt-get install git
    # Something here
    # End of file
    RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*


    RUN apt-get update && apt-get install -y git zip unzip && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
  29. #TIL : Changing channel from alpha to stable will remove ALL DATA

    On MacOS, changing Docker channel will remove all data (includes volumes, images, networks and ... everything).

    Because Docker on Mac using a minimal Linux machine to host docker engine, so changing machine means discarding all old data. So BECAREFUL !

  30. #TIL : zcat : decompressing pipe tool

    zcat is a tool that creates a pipe from gz file. It makes command cleaner and faster (maybe). You don't have to decompress gz file before using next tool.

    Examples :

    Finding string in gzip text file

    $ zcat secret.gz | grep '42'

    Importing SQL backup file

    $ mysqldump -u root -p db_name1 | gzip > db_name.sql.gz
    $ zcat db_name.sql.gz | mysql -u root -p db_name_2
  31. #TIL : Using BSD find util to find and exec command on file and folder

    Simple syntax of find

    $ find [find_path] -type [file_type] -exec [command] {} \;

    Add filename matching pattern to filter the result

    $ find [find_path] -name "*.php" -type [file_type] -exec [command] {} \;

    Where file_type is :

    • b : block special
    • c : character special
    • d : directory
    • f : regular file
    • l : symbolic link
    • p : FIFO
    • s : socket


    Fix common file and directory permissions

    $ find . -type f -exec chmod 644 {} \;
    $ find . -type d -exec chmod 755 {} \;

    Check syntax all PHP files

    $ find . -type f -name "*.php" -exec php -l {} \; | grep -v 'No syntax errors detected'

    Removed all log files

    $ find . -type f -name "*.log" -exec rm -f {} \;

    WANT MORE ???

    $ man find