Author: son

  • Webservers

    Webservers

    Về cơ bản bài viết này đưa cho các bạn khái niệm rất cơ bản về WebServer, các bạn web developer có thể rất cần Đầu tiên, mình nghĩ chúng ta nên đề cập đến HTTP, làm thế nào để match incoming HTTP request với website, sau đó là 2 Web Server rất phổ biến: Apache và Nginx, cuối cùng sẽ đề cập đến 1 ngôn ngữ cụ thể và cách kết nối với web server ở đây là PHP với PHP-FPM.

    HTTP, Web Server và Web Sites

    Mọi người có lẽ đều nghĩ rằng một WebServer chỉ có thể xử lý phục vụ một trang web, nhưng thực sự là ngược lại. Trong Apache thì dùng khái niệm VirtualHost, còn Nginx sử dụng bằng cách định nghĩa Server trong Nginx Configuration hay còn gọi là Virtual Servers.

    Nếu một WebServer đang xử lý nhiều trang web, làm thế nào để máy chủ định tuyến đến đúng trang web mà người dùng muốn truy cập?

    Chúng ta quay lại với HTTP – HyperText Transfer Protocol, là một trong năm giao thức chuẩn của mạng Internet, giao thức sử dụng để giao tiếp giữa WebServer và WebClient. Về cơ bản, WebServers sẽ đọc Host header của các Web HTTP request, nếu không tồn tại Host header hoặc không phù hợp, WebServer sẽ chuyển yêu cầu đến một trang web mặc định.

    Chúng ta có thể dùng curl để kiểm tra. Ví dụ mình sẽ kiểm tra magz.techover.io và Google.

    Chúng ta có thể thấy IP của WebServer là 104.28.19.140, chúng ta dùng curl để xem response khi gọi đến địa chỉ này.

    Chúng ta có thể thấy là magz.techover.io sử dụng Cloudflare để bảo vệ, và chúng ta bị chuyển đến trang mặc định 403 khi không có quyền truy cập.

    Còn với Google:

    Có thể thấy Google sử dụng GWS – Google Web Server. GWS thông báo cho Client rằng, Client cần phải truy cập đến http://www.google.com thông qua Location Header. Có 2 điều bạn thấy ở đây:

    • http://www.google.com mới là trang mặc định, thay vì http://google.com (cái này liên quan đến một khái niệm khác http://google.com được gọi là Naked Domain Name, sẽ có một bài viết liên quan đến vụ này sau).
    • GWS gửi một response chuyển hướng 301 đến http://www.google.com.

    Bây giờ nếu thêm Host header vào trang web thì sao:

    Kết quả không khả quan lắm, có vẻ như magz.techover.io và google.com vẫn không phải trang mặc định. Với trường hợp của magz.techover.io là do cloudflare chuyển hướng với non-SSL request sang SSL site.

    Đến đây một session mới được khởi tạo với Set-Cookie Header. Chúng ta có thể thử với một static site khác, site này không hề có Set-Cookie Header.

    Phần tiếp theo sẽ nói về việc cài đặt và cấu hình Nginx và Apache cho một hoặc nhiều Website.

  • Git Command Tips for Pros – Chap 1

    Git Command Tips for Pros – Chap 1

    Hôm nay mình sẽ tiếp tục với Git, bài này thực ra định để trong Series: Git from noob to master, tuy nhiên thì thấy cũng không hay ho lắm, nên quyết định tách riêng.

    Những ai cần đọc bài này

    Thực ra thì ai cũng đọc được, nhưng dùng thì không phải ai cũng cần, ví dụ nếu bạn quen thuộc với git graph (Tool Git GUI nào cũng có) và bạn thực sự hiểu thì cũng không cần lắm, tuy nhiên có một số command vẫn cần thiết, vì Tool không bao giờ toàn năng cả.

    Super Strong git help everyday


    git help everyday
    

    Câu lệnh này thực sự strong,

    Nó sẽ chỉ cho bạn biết các câu lệnh bạn cần dùng với các use-case, role khác nhau, ví dụ: Bạn là thằng dev đơn thuần hay là thằng quản lý repository.

    Git log với các tham số

    Thường thì ae sẽ làm như này

    git log
    

    hay ấn nhiều hơn một chút

    git log --oneline --graph
    

    để có cái sự đẹp đẽ như này

    Về cơ bản đều sử dụng git log, git log hỗ trợ một số tham số dòng lệnh, rất mạnh mẽ, đặc biệt là khi được sử dụng kết hợp để filter, đây là mấy cái khá hay ho

    • –author = "Son Hoang" – Chỉ hiển thị các cam kết được thực hiện bởi một tác giả nào đó, tất nhiên là dùng tên hiển thị
    • –name-only – Chỉ hiển thị tên của các tệp đã thay đổi
    • –oneline – Hiển thị dữ liệu cam kết được nén thành một dòng
    • –graph – Hiển thị cây phụ thuộc cho tất cả các xác nhận
    • –reverse – Hiển thị các cam kết theo thứ tự ngược lại (Cam kết cũ nhất trước)
    • — after – Hiển thị tất cả các cam kết đã xảy ra sau một số ngày nhất định
    • — before – Hiển thị tất cả các cam kết đã xảy ra trước một số dữ liệu nhất định Ví dụ: tôi cần tạo report hàng tuần được gửi mỗi thứ Sáu. Vì vậy, mỗi thứ Sáu, tôi sẽ chạy: git log --author="Alex Kras" --after="1 week ago" --oneline, chỉnh sửa một chút là xong.

    Anw: git log có nhiều param khi sử dụng CLI, nó thực sự mạnh và khá tiện hơn so với các GUI Tool, hãy đọc man git-log, một cái nữa --pretty khá là hay ho :).

    À vẫn có phần 2 nữa nhé

  • Git from noob to master – Chapter 2

    Git from noob to master – Chapter 2

    Trong một vài lần chém gió về Git, thấy mọi người có vẻ chưa chú ý nhiều đến Git và sử dụng nó một cách hiệu quả. Nhân đây xin mạn phép chém gió sơ qua để mọi người hoàn thiện.

    Git command

    Merge và Rebase (cont.)

    Tiếp theo lần trước, mình sẽ bắt đầu với merge

    Tại sao cần "merge"?.

    Đơn giản là vì chúng ta lập trình cùng nhau, nếu bạn quen dùng SVN, sẽ thấy là khi 2 người cùng làm việc (tất nhiên là song song với nhau), sẽ nảy sinh nhu cầu tạo một phiên bản là sự kết hợp giữa 2 phiên bản source code của 2 người

    Để merge được chúng ta cần 2 branch, dưới dây là một ví dụ

    alt text

    Chúng ta có 2 issue 55 và 56 trên hệ thống tracking, một cách nào đó developer có thể giải quyết 2 issues bằng một commit nhưng không phải lúc nào cũng thế và đặc biệt là không phải lúc nào cũng tốt, như là khi 1 trong 2 issues đó chưa được giải quyết triệt để tức là commit đó có vấn đề, rất khó để trace.

    Mọi người nên làm cách clear hơn, 1 hoặc 2 developer sẽ fix nó, ở các nhánh khác nhau.

    git checkout -b issue55
    git checkout -b issue56
    
    # -b for new branch
    

    alt text

    Họ modify source code ở mỗi nhánh và commit

    alt text

    Giờ chúng ta cần đưa phần thay đổi của 2 branch issue55 và issue56 vào master.

    git checkout master # change currrent branch to master
    git merge issue55
    ...
    git merge issue56
    

    alt text

    alt text

    Như vậy mỗi khi merge, chúng ta kết hợp 2 branch (hoặc commit, phần 3 mình sẽ giải thích kỹ hơn tại sao lại là commit) vào một nhánh, hoặc nghĩ đơn giản hơn là đưa những thay đổi ở nhánh này vào nhánh kia bằng một commit mới (chứa toàn bộ thay đổi).

    Ops!!! Git merge conflict

    alt text

    Tại sao conflict, đơn giản thôi, khi ở nhánh bạn merge vào, trong ví dụ issues55 là master bạn cũng có thay đổi. Ở ví dụ này là chúng ta có như sau

    alt text

    Mình có thay đổi ở master và issues1 cùng một dòng, git sẽ không biết chọn sự thay đổi nào. Nhiêu bạn sẽ sợ conflict và không biết làm thế nào và hỏi, câu trả lời là không thế nào cả, người merge sẽ là người quyết định. Có thể là chọn một trong 2, chọn cả 2 hoặc có thể phải làm lại cả đoạn đó.

    alt text

    Nghe nè: đừng bao giờ giải quyết conflict khi bạn không biết người khác vừa thay đổi cái gì, thật đấy.

    Rebase

    Cũng là một cách khác để đưa những thay đổi từ nhánh này sang nhánh khác nhưng khác hơn một chút: Bạn sẽ không tạo thêm commit mới mà đưa toàn bộ commit từ nhánh này sang nhánh kia.

    Quay lại với ví dụ conflict ở bên trên. Khi merge master vào nhánh issues1 chúng ta có

    alt text.

    Rebase thì sao:

    git checkout issues1
    git rebase master
    .... # conflict and resolve
    git add HelloWorldApp.java # add conflict file to tracking again
    git rebase --continue
    

    alt text.

    Như vậy có thể thấy là thay vì tạo commit mới, rebase sẽ đưa toàn bộ commit ở branch issues1 từ lúc branch out đặt lên cuối branch master, như vậy coi như là chúng ta không branch out từ một điểm trong quá khứ mà branch out từ lastest commit của master. À quên, vẫn có conflict và giải quyết nó như bình thường nhé :D.

    Advance Rebase (super strong)

    Thế giờ nếu có một nhánh khác được branch out từ nhánh issues1 mình có rebase lên master được không.

    Câu trả lời là có:

    Giả sử chúng ta có nhánh issues2 được branch out từ masterissues3 được branch out từ issues2.

    alt text.

    git rebase --onto master issues2 issues3
    

    Về cơ bản nó có ý nghĩa như sau:

    Hãy checkout nhánh issues3, và tìm các commit từ commit chung của nhánh issues3issues2, sau đó apply chúng vào nhánh master.

    alt text.

    Chú ý: không được rebase các commit mà bạn đã push lên repository. Nếu không ai cũng ghét và mọi người sẽ sỉ nhục và coi thường.

    Cơ bản là thế này, khi rebase bạn bỏ đi các commit và chuyển chúng sang chỗ khác. Khi bạn sửa các commit bằng rebase, từ một nhánh bạn pull từ repository, và push lên. Mọi người sẽ phải apply lại commit của họ và sẽ xảy ra nhất nhiều conflict khi bạn pull change các commit đó của họ về local.

  • F*** the people, who do not add Newline at End of File

    F*** the people, who do not add Newline at End of File

    Nghe có vẻ cứt bò, tuy nhiên sự thật là việc không add một trong trống ở cuối file thực sự là một tội ác

    No Newline at End of File

    Bạn đã bao giờ nhìn thấy dòng chữ ở git

    alt text

    hay ở vim

    alt text

    Ờ thế tại sao git lại báo thế, nó đến từ một quyết định trong quá khứ của Unix

    Một tệp nguồn không trống sẽ kết thúc bằng một ký tự dòng mới, không được đặt ngay trước ký tự dấu gạch chéo ngược (backslash).

    Vì đây là mệnh đề, nên chúng ta sẽ kiểm tra việc vi phạm quy tắc

    Vì vậy, nó chỉ ra rằng, theo POSIX, mọi tệp văn bản (bao gồm các tệp nguồn Ruby và JavaScript) phải kết thúc bằng một ký tự \n, hoặc mới newline (không phải là một dòng mới). Điều này đóng vai trò là eol, hoặc kết thúc của dòng nhân vật. Nó là một dòng Terminator.

    Bây giờ thì gần như mọi chương trình text editor đều hỗ trợ việc tự động thêm 1 dòng trống vào cuối file, ví dụ:

    • vim: mặc định rồi, nên là cứ để nó mặc định thôi
    • VSCode: dùng setting Files: Insert Final Newline
    • Sublime: dùng setting ensure_newline_at_eof_on_save

    Tóm lại là anh em nên thêm 1 dòng vào cuối file code nếu chưa có thì hãy sửa như sau:

    git ls-files -z | while IFS= read -rd '' f; do tail -c1 < "$f" | read -r _ || echo >> "$f"; done
    

    ref: https://unix.stackexchange.com/questions/31947/how-to-add-a-newline-to-the-end-of-a-file

  • How to recover corrupted GIT repository

    How to recover corrupted GIT repository

    GIT corrupted, really?

    Thực sự vấn đề này mình cũng không sure lắm là do đâu, và cũng không chắc vấn đề này có phải là corrupted hay không nhưng sẽ note lại một chút về case này.

    Nạn nhân

    Ngô Hải Đoàn, 1995, Android Dev. Anh ta đang làm việc trên PC, đột nhiên tòa nhà bị mất điện, khi bật máy lại anh ta phát hiện ra anh ta không thể thực hiện các câu lệnh git trên local-repository của mình nữa và mình là thằng cave được gọi support.

    Phán đoán

    Trước khi vào phần phán đoán thì mình có hỏi về source code đã commit chưa, nếu commit rồi thì khả năng recover được rất cao. Câu hỏi thứ 2, source code đó có quan trọng không, nếu có thể re-work trong dưới 30m thì chắc sẽ không có node này.

    Mình sẽ kết thúc phần phán đoán ở đây vì chả có gì để phán đoán cả

    Kiểm tra một chút.

    Trong khi voọc máy của Đoàn thì mình có cố re-init repository nhưng có vẻ không khả quan, kiểm tra một lúc thì có vẻ như các object và ref của git vẫn còn khá ổn. Bạn có thể tự kiểm tra thư mục .git trong local repository của mình.

    Như vậy, nhìn chung khả năng cao branch/commit quan trọng vẫn ổn.

    Thử recover.

    Mình có sử dụng một số câu lệnh git cơ bản như git log hay git init để thử lấy lại commit-id nhưng không thành công.

    Đến đây nhìn chung bạn không thể làm gì với repo này nữa, nên mình sẽ chuyển toàn bộ object của repo này sang một thư mục khác mà vừa clone về. (copy thư mục object trong .git của thư mục cũ sang chỗ tương ứng của thư mục mới)

    Đến đây bạn có một repository giống với remote (chỗ mà bạn clone về) và cộng thêm các commit mà bạn đã commit hoặc đã pull về từ remote.

    Tại sao lại copy objects

    Nhìn chung nếu bạn đã commit thì không sợ mất content. Bởi khi commit git sẽ sinh ra các file object trong thư mục objects, công với log trong logs và một số ref hay info.

    Object name sẽ dài 40 ký tự (SHA1)

    Thư mục object của bạn sẽ trông như này

    alt text

    Tên thư mục sẽ là 2 ký tự đầu trong 40 ký tự. Trong thư mục sẽ có các file với tên là 38 ký tự còn lại.

    Objects sẽ chứa thông tin về file (changed content) để xem được thì cần dùng câu lệnh git(do git mã hóa nên chỉ git xem đc :D): git cat-file

    alt text

    Đến đấy các bạn sẽ đặt câu hỏi thế git quản lý các file thành commit như thế nào

    Từ các objects thì git sẽ dựng lên tree là các phiên bản của thư mục bao gồm các objects.

    alt text

    alt text

    Cứ thế, bằng cách duyệt tree, ta sẽ có 1 tree hoàn chỉnh gồm content của cả một phiên bản (commit).

    Cuối cùng commit sẽ bao gồm 1 tree

    alt text

    Tóm lại cứ còn objects là bạn còn tất cả, việc còn lại là đi tìm commit-id để recover.

    Tìm commit

    Có một vài chỗ để bạn có thể tìm GIT commit-id, thứ nhất đó là thư mục refs

    Refs

    Refs chỉ đơn giản là references của commit. Refs dùng để bạn nhớ lastest commit bằng cách lưu commit id vào thư mục refs.

    alt text

    Ở đây lastest commit của nhánh master đang là b94514784b0b86e84bdd2d66903de5bf7f9722c2.

    Vậy nhớ được tên nhánh là có thể recover lại được. Lúc này bạn sẽ recover toàn bộ tree của nhánh đó và mặc nhiên các commit base trên commit này sẽ có thể trace được.

    logs

    Một chỗ nữa, toàn năng hơn là logs. Log lưu lại lịch sử của từng nhánh.

    alt text

    Bạn có thể xem mình đã tunglamgi trên từng nhánh.

    Đến đây bạn có commit-id rồi việc còn lại là recover bằng câu lệnh git checkout commit-id

    Btw

    Nhìn chung xử lý mấy việc lặt vặt này khá hay và tạo cho mình nhiều cơ hội xử lý các thủ thuật về git.

    Anw: Dù mất kì chuyện gì xảy ra đừng bao giờ xóa thư mục .git 😀

  • Git from noob to master – Chapter 1

    Git from noob to master – Chapter 1

    Trong một vài lần chém gió về Git, thấy mọi người có vẻ chưa chú ý nhiều đến Git và sử dụng nó một cách hiệu quả. Nhân đây xin mạn phép chém gió sơ qua để mọi người hoàn thiện.

    Git là gì

    Câu hỏi cơ bản và đơn giản nhưng thay vì trích dẫn bất kì định nghĩa nào mình sẽ quay sang từ khóa và hinh ảnh

    • SCM – Source code management
    • Linus Torvarlds (Linux)
    • Thay thế BitKeeper trong dự án Linux Kernel

    Cài đặt

    Git cung cấp bộ cài cho tất cả các OS hệ POSIX: Linux, Windows, macOS trên git-scm.

    Sơ lược lịch sử

    alt text.

    Torvalds thổ lộ rằng: ông chưa bao giờ muốn thực hiện quản lý source code, đó là công việc nhàm chán nhất trong thế giới máy tính (trừ database ra). Torvalds cùng các đồng đội sử dụng rất nhiều SCM khác nhau cho đến khi họ thấy phù hợp với BitKeeper(BK), thậm chí BK là nhân tố quan trong trong việc phát triển nhanh chóng của Linux Kernel. Vấn đề duy nhất của BK là một phần mềm độc quyền, tất nhiên có bản miễn phí với các hạn chế cho các open-source project. Larry McVoy(CEO BitMover công ty phát triển BK) vừa muốn hỗ trợ các dự án phần mềm tự do vừa muốn bảo vệ lợi ích của BK cũng như BitMover tất nhiên chừng nào hội phần mềm tự do chưa đe dọa đến lợi ích.

    Năm 2005, Andrew "Tridge" Tridgell đã dịch ngược BK, gần như ngay lập tức BK bỏ việc hỗ trợ Linux, ngược lại Linus cũng ngừng sử dụng BK để quản lý mã nguồn, tuy nhiên Linus chỉ có 3 tháng để chuyển toàn bộ source code sang công cụ mới khi BK chính thức ngừng hoàn toàn việc hỗ trợ. Điều đó nảy sỉnh việc phát triển Git.

    Quá trình phát triển bắt đầu từ ngày 3 tháng 4 nằm 2005, Torvalds công bố dự án vào ngày 6, Git có thể cài đặt trên PC vào ngày 7 và tính năng merge branch được release vào ngày 18. Đến ngày 16/6 Git thực hiện quản lý việc release Linux Kernel v2.6.12

    Có lẽ việc ôn lại lịch sử sẽ kết thúc ở đây, phần tiếp theo sẽ quay lại thực tế sử dụng Git

    Một số khái niệm trong Git

    Repository

    • Repository là khái niệm cơ bản của Git tương đương với project trong GitLab, Gerrit
    • Git có thể tạo bằng câu lệnh git init, thư mục trở thành local repository trong khi đó các repository online như trên GitLab được gọi là remote repository.
    • Lịch sử làm việc đều được lưu trong thư mục khởi tạo git

    Remote

    • Repository hosted in server. Remote repository chính thường được gọi là Origin
    • Các local clone đều liên kết đến remote.
    • 1 local clone can have 0, 1 or many remote.

    Branch – nhánh

    • Branch cũng là một khái niệm mới trong Git mà cần phải làm quen.
    • Branch là các version song song với nhau của Repo.
    • Người dùng làm việc trên các branch mà không làm ảnh hưởng đến live version.

    Một vài branch đặc biệt

    • master – branch mặc định
    • HEAD – branch hiện tại mà người dùng đang làm việc
    • origin/master, origin/xxx, origin2/xxx là các nhánh ở remote repository

    Checkout

    • Checkout là cách người ta chuyển nhánh đề làm việc
    • Ví dụ: Bạn lấy project trên GitLab về và cần chuyển qua nhánh master 2 để làm việc bạn cần checkout sang nhánh master 2: git checkout master2, hoặc cũng có thể bạn cần tạo ra một nhánh mới hãy thêm flag -b trong câu lệnh: git checkout -b dev_another_function.

    Commit

    • Nếu như Branch là nhánh cây, cành cây thì có thể coi commit chính là các nút (node) hoặc cũng có thể là một điểm nào đó trên nhánh.
    • Người ta lưu lịch sử làm việc trong các commit, nói cách khác nếu bạn commit dữ liệu của bạn không thể mất trừ khi bạn xóa hoàn toàn project git.
    • Cách tạo commit cũng đơn giản: git commit -m "Commit Message" hoặc cũng có thể đơn giản là git commit sau đó làm theo hướng dẫn với giao diện text editor(thường là vi, vim, nano, etc, ..)
    • Mỗi commit đều có message và một ID đặc biệt (SHA –hash), từ đó có thể trace được commit

    Nói đến đây mình đột nhiên nhiên phát hiện ra trình bay theo hướng này sẽ khiến mọi người khó hiểu một chút, vì vậy ngay sau đây mình sẽ trình bày về commit một cách rõ hơn, theo một cách nhin khác

    Git Concept

    alt text

    alt text

    2 hình trên đây đã trình bày cách sử dụng git ở local một cách cơ bản

    Nhìn chung một file sẽ có 4 trạng thái như hình thứ nhất

    • Untracked: Trong working directory nhưng git không quản lý, đó là nhưng file tạo mới, được copy vào hay đơn giản là bạn vừa chạy git rm fileName.
    • Unmodified: Rất dễ hiểu, đó là file git quản lý, git ghi nhận rằng file đó chưa có sự thay đổi so với commit hiện tại (HEAD). Có 2 cách để chuyển file vào trạng thái này đó là thêm các file untracked git add hay git commit tức là lưu sự thay đổi đó lại (file sẽ được ghi nhận là ko thay đổi so với commit mới :D, đôi chút confuse).
    • Modified: Là file từ trạng thái unmodified và đã bị edit, tất nhiên khi Crtl + Z toàn bộ step, file sẽ trở lại unmodified.
    • Staged: là trạng thái chuẩn bị được commit, thông thường người dùng không để ý đến trạng thái này, trạng thái này được trình bày khá rõ ràng ở hình thứ 2. Một trạng thái kiểu như git đã ghi nhận sự thay đổi nhưng chưa tạo commit. Để chuyển sang trạng thái staged sử dụng câu lệnh git stage.

    Một tips nhỏ với stage, khi bạn cần commit lên nhánh A mà lại làm việc trên nhánh B thì bạn có thể stage toàn bộ file cần thay đổi và checkout sang nhánh A và commit. Một cách khác đa số mọi người sẽ áp dụng đó là commit trên nhánh B, cherry-pick(sẽ nói ở dưới đây) commit sang A, ngoài ra cũng có cách chuyên nghiệp hơn đó là tạo pack diff.

    Merge và Rebase

    Từ thực tế làm việc trong nhóm sẽ nảy sinh các trường hợp phải kết hợp code của nhiều developer để tạo nên một bản hoàn chỉnh thay vì tiếp tục phát triển song song mãi điều đó nảy sinh ra 2 khái niệm trong git là merge và rebase.