Bài viết được sự cho phép của tác giả Nguyễn Hồng Quân
Những bạn đang dùng Windows mà tìm hiểu về Linux sẽ thấy trên Linux, những định dạng file nén quen thuộc như *.zip, *.7z lại không được ưa chuộng, mà lại thấy người ta hay sử dụng *.gz, *.tar.gz, *.zz, *.tar.xz, mặc dù cả định dạng và thuật toán của zip, 7zip đều là mã nguồn mở. Thế thì tại sao?
Đầu tiên, hãy nói về một định dạng file nén khác cực kì được ưa chuộng trên Windows là *.rar. Lý do định dạng này vắng mặt trên Linux thì dễ hiểu hơn, đó là nó không phải là phần mềm nguồn mở.
Quay lại *.zip và *.7z. Lý do chúng không được ưa chuộng là vì chúng không hỗ trợ nén và giải nén theo kiểu “cuốn chiếu”. Theo kiểu “cuốn chiếu” nghĩa là, ví dụ như bạn đang download một file nén lớn và bạn muốn download tới đâu, giải nén tới đó, không phải chờ download xong xuôi rồi mới giải nén. Tính năng “cuốn chiếu” này quan trọng đối với người dùng Linux vì trên Linux, môi trường dòng lệnh rất mạnh, có một tính năng gọi là “pipe” và tính “cuốn chiếu” kết hợp với “pipe” thì giúp công việc hiệu quả gấp nhiều lần.
Ví dụ, tôi hay sử dụng “pipe” (truyền dữ liệu đầu ra của chương trình này vào đầu vào của chương trình khác) khi tôi muốn copy cơ sở dữ liệu từ server về máy cá nhân:
$ ssh my-server 'pg_dump -O database_name' | psql database_name
Câu lệnh trên có nghĩa là:
- SSH vào server my-server, chạy lệnh
pg_dump
trên đó để dump dữ liệu PostgreSQL. Tuy nhiên kết quả dump không lưu vào file mà đẩy ra standard output (stdout). Khi bạn chạy lệnhpg_dump
trongssh
thì stdout củapg_dump
sẽ được ngầm download về, nhả ra qua stdout củassh
luôn. - Cùng lúc đó, chạy lệnh
psql
trên máy cá nhân để khôi phục dữ liệu đã dump. - Toán tử pipe (
|
) giúp kết nối stdout củassh
với standard input (stdin) củapsql
. Như vậy kết quả dump củapg_dump
sẽ đi thẳng vàopsql
mà không cần ra một file trung gian.
Trong trường hợp dữ liệu hơi lớn mà đường truyền Internet không quá nhanh thì tôi sẽ nén kết quả dump trước rồi mới gửi về máy cá nhân, bằng cách chèn thêm gzip
vào:
$ ssh my-server 'pg_dump -O database_name | gzip' | gunzip | psql database_name
Câu lệnh trên có nghĩa là:
- SSH vào server my-server, chạy lệnh
pg_dump
trên đó để dump dữ liệu PostgreSQL. Kết quả dump không lưu vào file mà đẩy ngay sang chogzip
để nén. Đầu ra đã nén sẽ được download và đi ra stdout của lệnhssh
. - Kết quả nén download được tới đâu, sẽ truyền ngay qua
gunzip
tới đó để giải nén. - Kết quả giải nén lại được truyền ngay vào
psql
để khôi phục dữ liệu mà không cần qua file trung gian.
Xem thêm tuyển dụng Linux lương cao trên TopDev
Nếu bạn muốn độ nén mạnh như 7zip thì bạn thay gzip bằng xz:
$ ssh my-server 'pg_dump -O database_name | xz' | unxz | psql database_name
Tất cả các ứng dụng trên, từ ssh
đến psql
đều xử lý dữ liệu theo kiểu “cuốn chiếu” nên kết hợp với “pipe” là tuyệt vời.
Nếu bạn thắc mắc tại sao có thể dùng lệnh pg_dump
và psql
một cách ngắn gọn, không cần cung cấp host, username, password, thì đọc thêm bài này.
Vì mục tiêu hỗ trợ nén & giải nén cả stream (luồng dữ liệu đang chảy) nên gzip, xz chỉ có thể làm việc với file đơn lẻ, không thể làm việc với cả thư mục như zip, 7zip. Để nén & giải nén thư mục thì người ta kết hợp với
tar
, một lệnh để đóng gói thư mục thành một file. Điều thú vị làtar
cũng đóng gói và mở gói thư mục theo kiểu “cuốn chiếu”.
Sau đây là một ví dụ khi tôi mua laptop mới và cần sao chép dữ liệu công việc từ laptop cũ sang laptop mới. Do dữ liệu rất lớn (hàng chục GiB), gồm hàng trăm ngàn file nhỏ nên không thể copy bằng phím Ctrl+C/Ctrl+V trong ứng dụng giao diện đồ họa được, do khi copy bằng cách này thì ứng dụng sẽ copy từng file một, sẽ cực kỳ lâu. Nén cả thư mục trước khi copy thì sẽ nhanh hơn, nhưng nếu dùng zip
, 7zip
thì sẽ gặp trở ngại là nó phải tạo ra file trung gian, trong khi ổ cứng không đủ để lưu file này, chưa kể sẽ phải chờ đợi file sinh ra trọn vẹn rồi mới copy và giải nén được. Trong trường hợp này, tôi kết hợp ssh
, tar
để không phải sinh ra file trung gian:
$ ssh old-laptop "tar -cO -C ~/Works folder-to-copy" | tar -xf-
Giải thích:
- Cờ
-c
trong lệnhtar
để yêu cầutar
thi hành đóng gói,-x
là để mở gói. -O
để yêu cầu tar đẩy kết quả đóng gói ra stdout.-C
để yêu cầutar
nhảy đến thư mục cha nào đó trước khi đóng gói thư mục con.-f -
(trong lệnhtar
thứ hai) để hướng dẫn lấy file đã đóng gói (đầu vào) từ standard input.
Ở đây, tôi dùng mạng dây nội bộ nên tốc độ truyền đủ nhanh để không cần nén, tuy nhiên nếu muốn nén thì có thể kết hợp với gzip:
$ ssh old-laptop "tar -cO -C ~/Works folder-to-copy | gzip" | gunzip | tar -xf-
hay ngắn gọn hơn:
$ ssh old-laptop "tar -czO -C ~/Works folder-to-copy" | tar -xzf-
Thêm một mẹo nhỏ, nếu bạn muốn theo dõi tiến độ của việc chuyển dữ liệu trên, bạn có thể kết hợp với pv
:
$ ssh old-laptop "tar -cO -C ~/Works folder-to-copy" | pv | tar -xf-
(Trong hình trên, tôi đang minh họa copy dữ liệu ở nơi có mạng chậm nên tốc độ hơi chậm).
Như vậy, trong bài này, không những bạn hiểu được lý do tại sao gzip
, xz
lại được ưa dùng hơn zip
, 7zip
mà còn được thấy sức mạnh của môi trường dòng lệnh trên Linux, ích lợi của môi trường dòng lệnh đối với năng suất công việc.
Bài viết gốc được đăng tải tại quan.hoabinh.vn
Xem thêm:
- Cấu hình Laravel Queue trên môi trường production
- Lợi ích và những hạn chế khi sử dụng SSH Tunneling
- Hướng dẫn kết nối PHP với SQL Server
Xem thêm các việc làm công nghệ hấp dẫn trên TopDev