Cơ bản về rsync: Lệnh và Cách sử dụng

rsync là công cụ thực hiện sao lưu tăng tiến. Khi kết hợp với lập lịch tác vụ, rsync có thể đồng bộ theo thời gian hoặc khoảng thời gian cố định. Kết hợp với inotify hoặc sersync, rsync có thể thực hiện đồng bộ theo thời gian thực dựa trên sự kiện.

rsync có thể thực hiện các chức năng sao chép từ xa như scp (rsync không hỗ trợ sao chép từ xa đến từ xa, nhưng scp hỗ trợ), sao chép cục bộ như cp, xóa như rm và hiển thị danh sách tệp như "ls -l". Tuy nhiên, cần lưu ý rằng mục đích cuối cùng của rsync hoặc mục đích ban đầu của nó là đồng bộ tệp giữa hai máy chủ, do đó các chức năng scp/cp/rm mà rsync thực hiện chỉ là phương tiện phụ trợ cho việc đồng bộ, và cách thức rsync thực hiện các chức năng này khác với các lệnh này. Thực tế, rsync có một thuật toán riêng, nguyên lý thuật toán và cơ chế thực hiện của rsync có thể phức tạp hơn nhiều so với suy nghĩ. Đối với việc sử dụng rsync để thực hiện các chức năng sao lưu, đồng bộ đơn giản, không cần quá sâu vào các nội dung lý thuyết này. Nhưng nếu muốn hiểu tài liệu man của lệnh rsync, sử dụng "-vvvv" để phân tích quá trình thực thi rsync, và triển khai các chức năng mạnh mẽ và hoàn chỉnh hơn của rsync, không có sự hỗ trợ của các kiến thức lý thuyết này là không thể. Bài viết này sẽ giới thiệu cách sử dụng và các chức năng thường dùng của rsync.

Trở lại chủ đề chính, đây là các nội dung cơ bản về rsync.

2.2 Giải thích cơ bản về đồng bộ rsync


Mục đích của rsync là đồng bộ tệp giữa máy chủ cục bộ và máy chủ từ xa (bao gồm cả đẩy từ cục bộ đến từ xa, kéo từ từ xa về cục bộ), cũng có thể đồng bộ tệp trong các đường dẫn khác nhau trên cục bộ, nhưng không thể đồng bộ giữa đường dẫn từ xa 1 đến đường dẫn từ xa 2 (scp có thể thực hiện).

Không xem xét chi tiết triển khai của rsync, đối với đồng bộ tệp, liên quan đến khái niệm tệp nguồn và tệp đích, cũng như việc xác định tệp nào là cơ sở đồng bộ. Ví dụ, nếu muốn tệp trên máy chủ đích giống với tệp cục bộ, thì tệp cục bộ là cơ sở đồng bộ, đẩy tệp cục bộ làm tệp nguồn đến máy chủ đích. Ngược lại, nếu muốn tệp trên máy chủ cục bộ giống với tệp trên máy chủ đích, thì tệp trên máy chủ đích là cơ sở đồng bộ, phương thức thực hiện là kéo tệp trên máy chủ đích làm tệp nguồn về cục bộ. Tất nhiên, để giữ cho hai tệp cục bộ đồng bộ với nhau, rsync cũng có thể thực hiện, giống như lệnh cp trong Linux, lấy một tệp cục bộ làm nguồn, một tệp khác làm tệp đích, nhưng xin lưu ý rằng mặc dù rsync và cp đạt được cùng một mục đích, nhưng cách thức triển khai của chúng là khác nhau.

Vì là đồng bộ tệp, trong quá trình đồng bộ chắc chắn sẽ liên quan đến vấn đề kiểm soát phiên bản giữa tệp nguồn và tệp đích, ví dụ như có nên xóa tệp tồn tại trên máy chủ đích nhưng không có trên máy chủ nguồn, tệp đích mới hơn tệp nguồn (newer than source) có nên vẫn giữ đồng bộ, khi gặp liên kết mềm là sao chép liên kết mềm本身 hay sao chép đối tượng mà liên kết mềm trỏ đến, khi tệp đích đã tồn tại có nên tạo bản sao lưu trước, v.v.

Quá trình đồng bộ rsync bao gồm hai phần: mô hình kiểm tra xác định tệp nào cần đồng bộ và mô hình đồng bộ khi tệp được đồng bộ.

(1). Mô hình kiểm tra là theo các quy tắc chỉ định để kiểm tra tệp nào cần được đồng bộ, ví dụ như tệp nào bị loại trừ rõ ràng không được truyền. Mặc định, rsync sử dụng thuật toán "quick check" để nhanh chóng kiểm tra kích thước tệp nguồn và tệp đích, thời gian sửa đổi (mtime) có khớp không, nếu không khớp thì cần truyền. Tất nhiên, cũng có thể thay đổi mô hình kiểm tra "quick check" bằng cách chỉ định một số tùy chọn trong dòng lệnh rsync, ví dụ như tùy chọn "--size-only" có nghĩa là "quick check" chỉ kiểm tra các tệp có kích thước khác nhau làm tệp cần truyền. rsync hỗ trợ rất nhiều tùy chọn, trong đó tính tùy biến của mô hình kiểm tra rất linh hoạt.

(2). Mô hình đồng bộ là các công việc bổ sung cần thực hiện trước khi quá trình đồng bộ diễn ra sau khi tệp được xác định cần đồng bộ. Ví dụ như đã nói ở trên, có nên xóa tệp tồn tại trên máy chủ đích nhưng không có trên máy chủ nguồn, có nên tạo bản sao lưu tệp đích đã tồn tại trước, có nên theo dõi các liên kết tệp, v.v. rsync cũng cung cấp rất nhiều tùy chọn làm cho mô hình đồng bộ trở nên linh hoạt hơn.

Thường thì việc chỉ định tùy chọn mô hình đồng bộ cho rsync bằng tay phổ biến hơn, chỉ khi có yêu cầu đặc biệt mới chỉ định mô hình kiểm tra, vì hầu hết các tùy chọn mô hình kiểm tra đều có thể ảnh hưởng đến hiệu suất của rsync.

2.3 Ba cách làm việc của rsync


Dưới đây là cú pháp của rsync:

Local:  rsync [OPTION...] SRC... [DEST]

Access via remote shell:
  Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST]
  Push: rsync [OPTION...] SRC... [USER@]HOST:DEST

Access via rsync daemon:
  Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]
        rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
  Push: rsync [OPTION...] SRC... [USER@]HOST::DEST
        rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST

Từ cú pháp này, chúng ta có thể thấy rsync có ba cách làm việc:

(1). Đồng bộ trên hệ thống tệp cục bộ. Cú pháp dòng lệnh là định dạng trong phần "Local" ở trên.

(2). Máy chủ cục bộ sử dụng remote shell để giao tiếp với máy chủ từ xa. Cú pháp dòng lệnh là định dạng trong phần "Access via remote shell" ở trên.

(3). Máy chủ cục bộ kết nối với rsync daemon trên máy chủ từ xa thông qua socket mạng. Cú pháp dòng lệnh là định dạng trong phần "Access via rsync daemon" ở trên.

Hai cách đầu tiên về cơ bản là giao tiếp qua ống, ngay cả khi là remote shell. Cách (3) là để máy chủ từ xa chạy rsync service, lắng nghe trên một cổng và chờ kết nối từ client.

Tuy nhiên, còn có cách làm việc thứ tư: có thể tạm thời khởi động rsync daemon qua remote shell, khác với cách (3), nó không yêu cầu máy chủ từ xa đã khởi động rsync service từ trước, mà là tạm thời tạo ra rsync daemon, đây là daemon một lần dùng chỉ để đọc tạm thời tệp cấu hình daemon, khi quá trình đồng bộ rsync hoàn tất, rsync daemon được khởi động bởi remote shell cũng sẽ tự động biến mất. Cú pháp dòng lệnh của phương thức giao tiếp này giống với "Access via rsync daemon", nhưng yêu cầu phần tùy chọn phải chỉ định rõ tùy chọn "--rsh" hoặc tùy chọn ngắn "-e".

Dưới đây là giải thích đơn giản về cú pháp rsync, vì rsync hỗ trợ hơn 100 tùy chọn, nên chỉ giới thiệu một vài tùy chọn thường dùng ở đây. Các tùy chọn đầy đủ và cách sử dụng rsync xem bản dịch "man rsync" của tôi.

Local:  rsync [OPTION...] SRC... [DEST]

Access via remote shell:
  Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST]
  Push: rsync [OPTION...] SRC... [USER@]HOST:DEST

Access via rsync daemon:
  Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]
        rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
  Push: rsync [OPTION...] SRC... [USER@]HOST::DEST
        rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST

Trong đó, tham số đường dẫn đầu tiên chắc chắn là đường dẫn tệp nguồn, tức là bên làm cơ sở đồng bộ, có thể chỉ định nhiều đường dẫn tệp nguồn cùng một lúc. Tham số đường dẫn cuối cùng là đường dẫn tệp đích, tức là bên cần đồng bộ. Định dạng đường dẫn có thể là đường dẫn cục bộ, hoặc đường dẫn từ xa sử dụng user@host:path hoặc user@host::path, nếu giữa máy chủ và đường dẫn path sử dụng dấu hai chấm đơn, có nghĩa là sử dụng phương thức giao tiếp remote shell, trong khi sử dụng dấu hai chấm kép thì có nghĩa là kết nối với rsync daemon. Ngoài ra, khi kết nối với rsync daemon, còn cung cấp cách biểu diễn đường dẫn theo định dạng URL rsync://user@host/path.

Nếu chỉ có một tham số SRC hoặc DEST, nó sẽ liệt kê danh sách tệp nguồn theo cách tương tự như "ls -l" (chỉ có một tham số đường dẫn, luôn được coi là tệp nguồn), thay vì sao chép tệp.

Nếu không quen thuộc với rsync, có thể chỉ hiểu tạm thời các định dạng đường dẫn cục bộ và remote shell user@host:path. Ví dụ:

[root@xuexi ~]# rsync /etc/fstab /tmp                # Đồng bộ cục bộ
[root@xuexi ~]# rsync -r /etc 172.16.10.5:/tmp       # Sao chép thư mục /etc cục bộ đến /tmp trên máy chủ từ xa, để đảm bảo thư mục /tmp trên máy chủ từ xa đồng bộ với /etc cục bộ
[root@xuexi ~]# rsync -r 172.16.10.5:/etc /tmp       # Sao chép thư mục /etc từ máy chủ từ xa đến /tmp cục bộ, để đảm bảo thư mục /tmp cục bộ đồng bộ với /etc trên máy chủ từ xa
[root@xuexi ~]# rsync /etc/                          # Liệt kê danh sách tệp trong thư mục /etc/ cục bộ
[root@xuexi ~]# rsync 172.16.10.5:/tmp/              # Liệt kê danh sách tệp trong thư mục /tmp/ trên máy chủ từ xa

Ngoài ra, cần lưu ý một điểm khi sử dụng rsync là nếu đường dẫn nguồn là một thư mục, có dấu gạch chéo cuối cùng và không có dấu gạch chéo cuối cùng là khác nhau. Không có dấu gạch chéo cuối cùng có nghĩa là toàn bộ thư mục bao gồm cả thư mục itself, có dấu gạch chéo cuối cùng có nghĩa là các tệp trong thư mục, không bao gồm thư mục itself. Ví dụ:

[root@xuexi ~]# rsync -a /etc /tmp
[root@xuexi ~]# rsync -a /etc/ /tmp

Lệnh đầu tiên sẽ tạo thư mục etc trong /tmp, trong khi lệnh thứ hai không tạo thư mục etc trong /tmp, các tệp trong đường dẫn nguồn /etc/ sẽ được đặt trực tiếp trong thư mục /tmp.

2.4 Giải thích tùy chọn và ví dụ


Tiếp theo là giải thích các tùy chọn của rsync.

-v: Hiển thị thông tin chi tiết trong quá trình rsync. Có thể sử dụng "-vvvv" để lấy thông tin chi tiết hơn.
-P: Hiển thị thông tin tiến độ truyền tệp. (Thực tế "-P"="--partial --progress", trong đó "--progress" mới là hiển thị thông tin tiến độ).
-n --dry-run: Chỉ kiểm tra truyền, không thực tế truyền. Thường kết hợp với "-vvvv" để xem rsync hoạt động như thế nào.
-a --archive: Chế độ lưu trữ, có nghĩa là truyền đệ quy và giữ thuộc tính tệp. Tương đương với "-rtopgDl".
-r --recursive: Đệ quy vào thư mục.
-t --times: Giữ thuộc tính mtime. <strong>Khuyên nên thêm "-t" mọi lúc, nếu không thuộc tính mtime của tệp đích sẽ được đặt thành thời gian hệ thống, dẫn đến việc kiểm tra cập nhật
          : phát hiện ra mtime khác nhau trong lần cập nhật tiếp theo, làm cho truyền tăng tiến vô hiệu.</strong>
-o --owner: Giữ thuộc tính owner (chủ sở hữu).
-g --group: Giữ thuộc tính group (nhóm).
-p --perms: Giữ thuộc tính perms (quyền, không bao gồm quyền đặc biệt).
-D        : Là sự kết hợp của "--device --specials", tức là cũng sao chép các tệp thiết bị và tệp đặc biệt.
-l --links: Nếu tệp là liên kết mềm, thì sao chép liên kết mềm itself thay vì đối tượng mà liên kết mềm trỏ đến.
-z        : Nén khi truyền để tăng hiệu quả.
-R --relative: Sử dụng đường dẫn tương đối. Có nghĩa là gửi toàn bộ đường dẫn được chỉ định trong dòng lệnh thay vì tên tệp ở cuối đường dẫn cho máy chủ, bao gồm cả thuộc tính của chúng. Xem ví dụ dưới đây.
--size-only : Thuật toán mặc định là kiểm tra tệp có kích thước và mtime khác nhau, sử dụng tùy chọn này sẽ chỉ kiểm tra tệp có kích thước khác nhau.
-u --update : Chỉ sao chép khi mtime của nguồn mới hơn mtime của tệp đã tồn tại trên đích. Lưu ý rằng tùy chọn này được xác định trên máy nhận, không ảnh hưởng đến hành vi xóa.
-d --dirs   : Sao chép thư mục itself mà không đệ quy. Mặc định khi đệ quy, nếu nguồn là "dir1/file1", thì không sao chép thư mục dir1, sử dụng tùy chọn này sẽ sao chép dir1 nhưng không sao chép file1.
--max-size  : Giới hạn kích thước tệp lớn nhất được rsync truyền. Có thể sử dụng hậu tố đơn vị, cũng có thể là một giá trị thập phân (ví dụ: "--max-size=1.5m")
--min-size  : Giới hạn kích thước tệp nhỏ nhất được rsync truyền. Điều này có thể được sử dụng để ngăn chặn việc truyền các tệp nhỏ hoặc các tệp rác.
--exclude   : Chỉ định quy tắc loại trừ để loại trừ các tệp không cần truyền.
--delete    : Dựa trên SRC, đồng bộ DEST. Nhiều thì xóa, ít thì bổ sung. Lưu ý "--delete" được thực hiện trên máy nhận, vì vậy nó được thực hiện sau khi các quy tắc exclude/include có hiệu lực.
-b --backup : Tạo bản sao lưu cho tệp đã tồn tại trên đích, tên bản sao lưu mặc định sử dụng "~" làm hậu tố.
--backup-dir: Chỉ định đường dẫn lưu trữ tệp sao lưu. Nếu không chỉ định, mặc định lưu cùng thư mục với tệp cần sao lưu.
-e          : Chỉ định chương trình remote shell cần sử dụng, mặc định là ssh.
--port      : Cổng được sử dụng khi kết nối daemon, mặc định là cổng 873.
--password-file: Tệp mật khẩu trong chế độ daemon, có thể đọc mật khẩu từ đó để thực hiện không tương tác. Lưu ý rằng đây không phải là mật khẩu xác thực remote shell, mà là mật khẩu xác thực mô-đun rsync.
-W --whole-file: rsync sẽ không sử dụng truyền tăng tiến, mà là truyền toàn bộ. Khi băng thông mạng cao hơn băng thông đĩa, tùy chọn này hiệu quả hơn truyền tăng tiến.
--existing  : Yêu cầu chỉ cập nhật các tệp đã tồn tại trên đích, các tệp chưa tồn tại trên đích không truyền. Lưu ý rằng khi sử dụng đường dẫn tương đối, nếu thư mục upper-level không tồn tại thì cũng không truyền.
--ignore-existing: Yêu cầu chỉ cập nhật các tệp không tồn tại trên đích. Khi kết hợp với "--existing" có chức năng đặc biệt, xem ví dụ dưới đây.
--remove-source-files: Yêu cầu xóa tệp nguồn đã truyền thành công.

rsync có rất nhiều tùy chọn, có thể thực hiện các chức năng rất linh hoạt, các tùy chọn ở trên chỉ là một phần rất nhỏ các tùy chọn thường dùng, về các tùy chọn đầy đủ và chi tiết hơn, xem bản dịch tài liệu man rsync của tôi.

Mặc dù có rất nhiều tùy chọn, nhưng tổ hợp tùy chọn thường dùng nhất là "avz", tức là nén và hiển thị một phần thông tin, và truyền ở chế độ lưu trữ.

2.4.1 Ví dụ cơ bản

Dưới đây là một vài ví dụ đồng bộ cục bộ và đồng bộ qua remote shell, trong ví dụ không sử dụng tùy chọn "-a", mục đích là để làm rõ vai trò của từng tùy chọn.

(1). Sao chép /etc/fstab đến thư mục /tmp.

[root@xuexi ~]# rsync /etc/fstab /tmp

(2). Sao chép thư mục /etc/cron.d đến /tmp.

[root@xuexi ~]# rsync -r /etc/cron.d /tmp

Lệnh này sẽ tạo thư mục /tmp/cron.d trên máy chủ đích, và đặt các tệp trong /etc/cron.d vào thư mục /tmp/cron.d, tức là mặc định, không tạo thư mục upper-level /etc trong đường dẫn thư mục.

(3). Sao chép thư mục /etc/cron.d đến /tmp, nhưng yêu cầu tạo thư mục etc con trong /tmp.

[root@xuexi ~]# rsync -R -r /etc/cron.d /tmp

Trong đó tùy chọn "-R" có nghĩa là sử dụng đường dẫn tương đối, đường dẫn tương đối này là dựa trên thư mục đích. Đối với ví dụ trên, có nghĩa là tạo thư mục etc/cron.d trên đích, tức là /tmp/etc/cron.d, gốc "/" của etc/cron.d đại diện cho thư mục đích /tmp.

Nếu đường dẫn nguồn cần sao chép dài, nhưng chỉ muốn giữ một phần cấu trúc thư mục trên máy chủ đích, ví dụ như muốn sao chép /var/log/anaconda/* đến /tmp, nhưng chỉ muốn giữ cấu trúc thư mục bắt đầu từ log, làm thế nào để thực hiện? Sử dụng một dấu chấm đại diện cho điểm bắt đầu đường dẫn tương đối, tức là chia đường dẫn dài.

[root@xuexi ~]# rsync -R -r /var/./log/anaconda /tmp

Như vậy, các thư mục bắt đầu từ dấu chấm đều là đường dẫn tương đối, gốc tương đối của chúng là thư mục đích. Vì vậy đối với ví dụ trên, sẽ tạo /tmp/log/anaconda/* trên đích.

(4). Tạo bản sao lưu cho các tệp đã tồn tại trong thư mục từ xa.

[root@xuexi ~]# rsync -R -r --backup /var/./log/anaconda /tmp

Như vậy trong thư mục đích, các tệp đã tồn tại sẽ được tạo bản sao lưu, tên bản sao lưu mặc định sử dụng "~" làm hậu tố, có thể sử dụng "--suffix" để chỉ định hậu tố sao lưu.

[root@xuexi tmp]# ll log/anaconda/
total 3112
-rw------- 1 root root    6668 Jul 14 12:45 anaconda.log
-rw------- 1 root root    6668 Jul 14 11:44 anaconda.log~
-rw------- 1 root root    3826 Jul 14 12:45 ifcfg.log
-rw------- 1 root root    3826 Jul 14 11:44 ifcfg.log~
-rw------- 1 root root 1102699 Jul 14 12:45 journal.log
-rw------- 1 root root 1102699 Jul 14 11:44 journal.log~
-rw------- 1 root root       0 Jul 14 12:45 ks-script-1uLekR.log
-rw------- 1 root root       0 Jul 14 11:44 ks-script-1uLekR.log~
-rw------- 1 root root       0 Jul 14 12:45 ks-script-iGpl4q.log
-rw------- 1 root root       0 Jul 14 11:44 ks-script-iGpl4q.log~
-rw------- 1 root root  160420 Jul 14 12:45 packaging.log
-rw------- 1 root root  160420 Jul 14 11:44 packaging.log~
-rw------- 1 root root   27906 Jul 14 12:45 program.log
-rw------- 1 root root   27906 Jul 14 11:44 program.log~
-rw------- 1 root root   78001 Jul 14 12:45 storage.log
-rw------- 1 root root   78001 Jul 14 11:44 storage.log~
-rw------- 1 root root  197961 Jul 14 12:45 syslog
-rw------- 1 root root  197961 Jul 14 11:44 syslog~

Có thể sử dụng "--backup-dir" để chỉ định đường dẫn lưu trữ tệp sao lưu, nhưng yêu cầu đường dẫn lưu trữ phải tồn tại.

[root@xuexi ~]# mkdir /tmp/log_back

[root@xuexi ~]# rsync -R -r --backup --backup-dir=/tmp/log_back /var/./log/anaconda /tmp

Chỉ định đường dẫn sao lưu sau, mặc định sẽ không thêm hậu tố sao lưu, trừ khi sử dụng "--suffix" để chỉ định hậu tố rõ ràng, ví dụ "--suffix=~".

[root@xuexi tmp]# tree /tmp/log_back/
/tmp/log_back/
└── log
    └── anaconda
        ├── anaconda.log
        ├── ifcfg.log
        ├── journal.log
        ├── ks-script-1uLekR.log
        ├── ks-script-iGpl4q.log
        ├── packaging.log
        ├── program.log
        ├── storage.log
        └── syslog

(5). Chỉ định tham số kết nối ssh, như cổng, người dùng kết nối, tùy chọn ssh, v.v.

[root@xuexi tmp]# >~/.ssh/known_hosts   # Đầu tiên xóa host key để kiểm tra

[root@xuexi tmp]# rsync -e "ssh -p 22 -o StrictHostKeyChecking=no" /etc/fstab 172.16.10.5:/tmp
Warning: Permanently added '172.16.10.5' (RSA) to the list of known hosts.
root@172.16.10.5's password:

Có thể thấy rằng chỉ định trực tiếp tham số ssh là có hiệu lực.

(6)."--existing" và "--ignore-existing"

"--existing" chỉ cập nhật các tệp đã tồn tại trên đích.

Hiện tại nội dung trong /tmp/{a,b} như sau, bashrc trong thư mục a, crontab trong thư mục b, và thư mục a có một thư mục con c.

[root@xuexi ~]# tree /tmp/{a,b}
/tmp/a
├── bashrc
├── c
│   └── find
├── fstab
├── profile
└── rc.local
/tmp/b
├── crontab
├── fstab
├── profile
└── rc.local
 
1 directory, 9 files

Sử dụng tùy chọn "--existing" để chỉ cập nhật các tệp đã tồn tại trên đích.

[root@xuexi ~]# rsync -r -v --existing /tmp/a/ /tmp/b           
sending incremental file list
fstab
profile
rc.local
 
sent 2972 bytes  received 70 bytes  6084.00 bytes/sec
total size is 204755  speedup is 67.31

Kết quả chỉ có 3 tệp đã tồn tại trên đích được cập nhật, vì trên đích không có thư mục c, nên các tệp trong thư mục c cũng không được truyền.

Trong khi "--ignore-existing" là cập nhật các tệp không tồn tại trên đích.

[root@xuexi ~]# rsync -r -v --ignore-existing /tmp/a/ /tmp/b
sending incremental file list
bashrc
c/
c/find
 
sent 202271 bytes  received 54 bytes  404650.00 bytes/sec
total size is 204755  speedup is 1.01

Khi "--existing" và "--ignore-existing" kết hợp sử dụng, có một hiệu ứng đặc biệt, khi chúng kết hợp với "--delete", tệp sẽ không được truyền, nhưng sẽ xóa các tệp dư thừa trên máy nhận.

$ mkdir a b
$ touch a/{1..4}.txt
$ touch b/a.log

$ rsync -nrv --delete a/ b/
sending incremental file list
deleting a.log
1.txt
2.txt
3.txt
4.txt
 
sent 118 bytes  received 33 bytes  302.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)

$ rsync -nrv --existing --ignore-existing --delete a/ b/
sending incremental file list
deleting a.log
 
sent 106 bytes  received 21 bytes  254.00 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)

Thực tế, "--existing" và "--ignore-existing" là quy tắc truyền, chỉ ảnh hưởng đến danh sách tệp mà máy nhận yêu cầu máy gửi truyền, trong quá trình máy nhận quyết định哪些 tệp cần truyền trước khi thực hiện, hai tùy chọn này không thể kiểm soát, vì vậy các quy tắc, "--delete" và các hoạt động khác đều không bị ảnh hưởng bởi hai tùy chọn này.

(7)."--remove-source-files" xóa tệp nguồn.

Sau khi sử dụng tùy chọn này, các tệp đã được cập nhật thành công trên nguồn sẽ bị xóa, các tệp chưa được truyền hoặc truyền không thành công trên nguồn sẽ không bị xóa. Các nguyên nhân truyền không thành công có nhiều, như exclude loại trừ, "quick check" không chọn tệp, truyền bị gián đoạn, v.v.

Tóm lại, các tệp hiển thị trong danh sách truyền của "rsync -v" sẽ bị xóa. Ví dụ:

[root@xuexi ~]# rsync -r -v --remove-source-files /tmp/a/anaconda /tmp/a/audit /tmp       
sending incremental file list
anaconda/anaconda.log
anaconda/ifcfg.log
anaconda/journal.log
anaconda/ks-script-1uLekR.log
anaconda/ks-script-iGpl4q.log
anaconda/packaging.log
anaconda/program.log
anaconda/storage.log
anaconda/syslog
audit/audit.log
 
sent 4806915 bytes  received 204 bytes  9614238.00 bytes/sec
total size is 4805676  speedup is 1.00

Các tệp được hiển thị ở trên trên nguồn đều bị xóa.

2.4.2 "--exclude" quy tắc loại trừ

Sử dụng tùy chọn "--exclude" để chỉ định quy tắc loại trừ, loại trừ các tệp không cần truyền.

[root@xuexi tmp]# rsync -r -v --exclude="anaconda/*.log" /var/log/anaconda /var/log/audit /tmp
sending incremental file list
anaconda/
anaconda/syslog
audit/
audit/audit.log
 
sent 3365629 bytes  received 58 bytes  6731374.00 bytes/sec
total size is 3365016  speedup is 1.00

Trong ví dụ trên chỉ loại trừ các tệp log trong thư mục anaconda, nhưng các tệp log trong thư mục audit được truyền bình thường.

Lưu ý rằng một "--exclude" chỉ có thể chỉ định một quy tắc, để chỉ định nhiều quy tắc loại trừ, cần sử dụng nhiều tùy chọn "--exclude", hoặc viết các quy tắc loại trừ vào tệp, sau đó sử dụng tùy chọn "--exclude-from" để đọc tệp quy tắc.

Ngoài "--exclude" quy tắc loại trừ, còn có "--include" quy tắc bao gồm, như tên gọi, nó là lọc ra các tệp cần truyền, vì vậy quy tắc include cũng được gọi là quy tắc truyền. Cách sử dụng của nó giống với "--exclude". Nếu một tệp vừa khớp với quy tắc loại trừ, vừa khớp với quy tắc bao gồm, thì quy tắc khớp trước sẽ có hiệu lực ngay lập tức, sau khi có hiệu lực sẽ không khớp thêm nữa.

Cuối cùng, về quy tắc, điểm quan trọng nhất là thời điểm có hiệu lực của nó. Khi máy gửi gõ lệnh rsync, rsync sẽ ngay lập tức quét các tệp và thư mục được chỉ định trong dòng lệnh (quá trình quét cũng sẽ sắp xếp theo thư mục, đặt các tệp trong cùng một thư mục ở vị trí liền kề), điều này được gọi là cây sao chép (copy tree), sau khi quét xong, các tệp hoặc thư mục cần truyền sẽ được ghi vào danh sách tệp, sau đó danh sách tệp sẽ được truyền cho máy nhận. Thời điểm có hiệu lực của quy tắc lọc là khi quét cây sao chép, vì vậy sẽ khớp theo quy tắc và quyết định tệp có được ghi vào danh sách tệp hay không (chính xác là sẽ được ghi vào danh sách tệp, chỉ là các tệp bị loại trừ sẽ được đánh dấu là ẩn đi), chỉ có các tệp hoặc thư mục được ghi vào danh sách tệp mới là nội dung thực sự cần truyền. Nói cách khác, thời điểm có hiệu lực của quy tắc lọc trong toàn bộ quá trình đồng bộ rsync rất sớm, nó sẽ ảnh hưởng đến nhiều đối tượng hoạt động của các tùy chọn, điển hình nhất là "--delete". Có thể bạn đọc xong cả bài viết này mà không cảm thấy tầm quan trọng của điểm này, nhưng nếu bạn đọc tài liệu man của rsync hoặc học nguyên lý của rsync, bạn chắc chắn sẽ có trải nghiệm sâu sắc.

Thực tế, quy tắc loại trừ và quy tắc bao gồm chỉ là hai quy tắc đặc biệt của "--filter". "--filter" khá phức tạp, nó có cú pháp quy tắc và mô hình khớp riêng, do giới hạn về không gian, cũng như xem xét mức độ khó của bài viết này, "--filter" không tiện giải thích nhiều ở đây, chỉ đơn giản giải thích về các loại quy tắc, giúp hiểu "--delete" dưới đây.

Dưới đây là các loại quy tắc trong rsync, những điểm không hiểu có thể kết hợp với "--delete" để phân tích:

(1). exclude quy tắc: tức là quy tắc loại trừ, chỉ có hiệu lực trên máy gửi, các tệp bị loại trừ sẽ không vào danh sách tệp (thực tế là thêm quy tắc ẩn để ẩn đi).

(2). include quy tắc: tức là quy tắc bao gồm, cũng được gọi là quy tắc truyền, chỉ có hiệu lực trên máy gửi, các tệp được bao gồm sẽ được ghi rõ vào danh sách tệp.

(3). hide quy tắc: tức là quy tắc ẩn, chỉ có hiệu lực trên máy gửi, các tệp bị ẩn sẽ không được máy nhận nhìn thấy, tức là máy nhận sẽ coi chúng không tồn tại trên nguồn.

(4). show quy tắc: tức là quy tắc hiển thị, chỉ có hiệu lực trên máy gửi, là quy tắc ngược của quy tắc ẩn.

(5). protect quy tắc: tức là quy tắc bảo vệ, quy tắc này chỉ có hiệu lực trên máy nhận, các tệp được bảo vệ sẽ không bị xóa.

(6). risk quy tắc: tức là quy tắc hủy bảo vệ. Là ngược lại của protect.

Ngoài ra, còn có một loại quy tắc là "clear quy tắc", có tác dụng xóa danh sách include/exclude quy tắc.

2.4.2.1 Làm thế nào để viết đúng quy tắc exclude một lần

Nhiều người không viết được quy tắc, luôn thấy rằng viết ra rồi không có hiệu lực, để viết đúng một quy tắc cần phải liên tục gỡ lỗi, gỡ lỗi, gỡ lỗi, gây ra sự khó chịu vô cùng.

Thực tế, cách viết quy tắc của nhiều công cụ là tương tự, ví dụ như tar cũng vậy. Nguyên nhân viết xong không có hiệu lực thường là hai loại: vấn đề đường dẫn tuyệt đối và đường dẫn tương đối, vấn đề dấu gạch chéo cuối cùng.

Thường thì đường dẫn hoạt động là đường dẫn tuyệt đối, thì quy tắc phải viết đường dẫn tuyệt đối, và phải viết đường dẫn tuyệt đối đầy đủ. Đường dẫn hoạt động là đường dẫn tương đối, thì quy tắc phải viết đường dẫn tương đối, bắt đầu từ đâu có thể phụ thuộc vào công cụ. Ví dụ, để hoạt động đường dẫn "/abc/def", muốn lọc tất cả các tệp txt trong def, phải viết thành "/abc/def/.txt", nếu đường dẫn hoạt động là "abc/def", thì để lọc tất cả các tệp txt trong thư mục này, có thể cần viết thành "abc/def/.txt", cũng có thể viết thành ".txt", thậm chí viết thành "def/.txt", viết theo loại hình nào phụ thuộc vào cách phần mềm phân tích đường dẫn tương đối.

Đối với rsync, phức tạp hơn một chút, vì ngoài đường dẫn tương đối của bash, nó còn cung cấp một quy tắc phân tích đường dẫn tương đối riêng, và dấu gạch chéo cuối cùng cũng ảnh hưởng đến cách viết quy tắc. Đây là lý do tại sao viết quy tắc rsync rất khó khăn.

Tôi cung cấp một cách để xác định cách viết quy tắc, hoàn toàn là kinh nghiệm cá nhân: sử dụng tùy chọn "-n" là chế độ dry run, tức là chỉ kiểm tra không truyền, tùy chọn "-i" là xuất đường dẫn tệp cần truyền. "-i" chỉ là một tùy chọn tiện lợi, có thể thay thế bằng các tùy chọn khác để tùy chỉnh định dạng đầu ra, đôi khi sử dụng các thông tin này để đưa ra một số phán đoán rất hữu ích, cụ thể có thể xem tài liệu man.

root:~$ rsync -nr -i a b/
cd+++++++++ a/
>f+++++++++ a/1.txt
>f+++++++++ a/2.txt
>f+++++++++ a/3.txt
>f+++++++++ a/4.txt

Ở đây đã hiển thị đường dẫn tệp truyền "a/*", tức là bao gồm cả thư mục a, và là đường dẫn tương đối. Vì vậy khi viết quy tắc, cần thêm tiền tố a này, ví dụ như quy tắc loại trừ dưới đây.

root:~$ rsync -nr -i --exclude="a/2.txt"  a b/
cd+++++++++ a/
>f+++++++++ a/1.txt
>f+++++++++ a/3.txt
>f+++++++++ a/4.txt

root:~$ rsync -nr -i --exclude="a/*.txt"  a b/
cd+++++++++ a/

Nếu đường dẫn truyền ở trên a thêm dấu gạch chéo cuối cùng, xem thông tin đường dẫn đầu ra của -i, phát hiện đã thay đổi:

root:~$ rsync -nr -i a/ b/
>f+++++++++ 1.txt
>f+++++++++ 2.txt
>f+++++++++ 3.txt
>f+++++++++ 4.txt

Vì vậy, quy tắc loại trừ ở đây không nên bao gồm tiền tố thư mục a:

root:~$ rsync -nr -i --exclude="2.txt" ./a/ b/
>f+++++++++ 1.txt
>f+++++++++ 3.txt
>f+++++++++ 4.txt

2.4.3 Giải thích "--delete"

Sau khi sử dụng tùy chọn "--delete", rsync trên máy nhận sẽ xóa các tệp đã tồn tại trên thư mục đích nhưng không tồn tại trên thư mục nguồn. Tức là "nhiều thì xóa, ít thì bổ sung".

Ví dụ, trước tiên thực hiện đồng bộ một lần, sau đó sao chép một tệp mới vào thư mục đích, như vậy thư mục đích sẽ có một tệp nhiều hơn thư mục nguồn.

[root@xuexi ~]# rsync -r /etc/cron.d /tmp/

[root@xuexi ~]# cp /etc/fstab /tmp/cron.d/

[root@xuexi ~]# ls /tmp/cron.d/
0hourly  fstab  raid-check  sysstat

Sau đó sử dụng tùy chọn "--delete", lúc này sẽ xóa tệp dư thừa trên đích, sau đó thực hiện đồng bộ.

[root@xuexi ~]# rsync -r -v /etc/cron.d /tmp --delete
sending incremental file list
deleting cron.d/fstab
cron.d/0hourly
cron.d/raid-check
cron.d/sysstat
 
sent 704 bytes  received 70 bytes  1548.00 bytes/sec
total size is 471  speedup is 0.61

Hành vi này thực hiện chức năng xóa từ xa, đối với rsync hoạt động trên cục bộ, cũng thực hiện chức năng xóa cục bộ như rm. Và nếu sử dụng thư mục trống làm nguồn, thì chức năng của nó là xóa toàn bộ thư mục.

Nếu kết hợp tùy chọn "--delete" với tùy chọn "--exclude", các tệp bị loại trừ sẽ không bị xóa. Ví dụ:

[root@xuexi ~]# rsync -r /var/log/anaconda /var/log/audit /tmp  # Đầu tiên thực hiện đồng bộ một lần để kiểm tra

[root@xuexi ~]# cp /etc/fstab /tmp/anaconda/                    # Sao chép một tệp mới vào thư mục đích để kiểm tra

[root@xuexi ~]# rsync -r -v --exclude="anaconda/*.log" /var/log/anaconda /var/log/audit /tmp --delete
sending incremental file list
deleting anaconda/fstab
anaconda/syslog
audit/audit.log
 
sent 3406190 bytes  received 52 bytes  6812484.00 bytes/sec
total size is 3405579  speedup is 1.00

Kết quả phát hiện chỉ xóa tệp "anaconda/fstab", các tệp anaconda/*.log khớp với quy tắc "--exclude" đều không bị xóa. Tức là lời nói trên mạng: các tệp bị loại trừ bởi exclude sẽ không bị xóa.

Kết luận là đúng, nhưng tôi nghĩ nhiều người không biết tại sao lại như vậy, có thể chưa bao giờ nghĩ tại sao, vì vậy tôi sẽ giải thích đơn giản.

Sau khi máy gửi gửi danh sách tệp cho máy nhận, tiến trình generator của máy nhận (nếu không biết, bạn có thể coi đó là một tiến trình nào đó) sẽ quét từng thông tin trong danh sách tệp, sau đó tính toán mã kiểm tra khối dữ liệu cho từng mục thông tin, cuối cùng gửi mã kiểm tra khối dữ liệu cho máy gửi, máy gửi khớp các khối dữ liệu cần truyền qua mã kiểm tra, như vậy thực hiện chức năng truyền tăng tiến - chỉ truyền các phần đã thay đổi, không truyền toàn bộ tệp. Thời điểm xóa delete là khi tiến trình generator xử lý từng danh sách tệp, trước khi tạo mã kiểm tra, trước tiên xóa các tệp dư thừa tồn tại trên đích nhưng không tồn tại trên nguồn, như vậy không cần tạo mã kiểm tra cho các tệp dư thừa.

Vì vậy, hành động delete được thực hiện muộn hơn quy tắc "--exclude", các tệp bị quy tắc exclude loại trừ sẽ không vào danh sách tệp, khi thực hiện delete sẽ coi các tệp này không tồn tại trên nguồn, dẫn đến việc xóa các tệp này trên đích. Nhưng đây là suy nghĩ đơn giản, mặc dù về lý thuyết đúng là như vậy, nhưng rsync để ngăn chặn nhiều trường hợp xóa nhầm, cung cấp hai quy tắc: quy tắc bảo vệ (protect) và quy tắc hủy bảo vệ (risk). Mặc định, khi "--delete" và "--exclude" cùng sử dụng, mặc dù máy gửi đánh dấu các tệp bị loại trừ là ẩn, làm cho máy nhận cho rằng các tệp này không tồn tại trên nguồn, nhưng rsync sẽ đánh dấu các tệp này là tệp được bảo vệ, làm cho chúng không bị ảnh hưởng bởi hành vi delete, như vậy delete sẽ không xóa được các tệp này. Nếu vẫn muốn buộc xóa các tệp bị exclude loại trừ, có thể sử dụng tùy chọn "--delete-excluded" để hủy bảo vệ, như vậy ngay cả khi các tệp bị loại trừ cũng sẽ bị xóa.

Vậy bây giờ, bạn đã hiểu lời nói trên mạng "các tệp bị loại trừ bởi exclude sẽ không bị xóa"?

Ngoài "--delete", các tùy chọn liên quan còn có "--delete-before", "--delete-during", "--delete-delay", v.v., chúng đều ngầm chứa tùy chọn "--delete", chúng lần lượt biểu thị generator xử lý từng danh sách tệp trước khi xóa tất cả các tệp cần xóa, xử lý danh sách tệp nào thì xóa tệp trong danh sách đó, và sau khi đồng bộ tất cả dữ liệu thì xóa tất cả các tệp cần xóa.

Ví dụ, giả sử nguồn cần truyền 3 thư mục a, b, c, trên đích thư mục a có a1, a2, a3 tổng cộng 3 tệp cần xóa, thư mục b có b1, b2, b3 cần xóa, tương tự thư mục c cũng có c1, c2, c3 cần xóa.

Nếu là "--delete-before", thì khi rsync trên đích vừa khởi động, sẽ xóa a1-a3, b1-b3, c1-c3 một lần, sau đó mới xử lý danh sách tệp của thư mục a, xử lý xong a thì xử lý b, rồi đến c.

Nếu là "--delete-during", thì khi rsync trên đích vừa khởi động, trước tiên xử lý danh sách tệp của thư mục a, khi xử lý thư mục a phát hiện thư mục này có các tệp cần xóa a1-a3, liền tay xóa chúng, sau đó hoàn thành các hoạt động liên quan đến thư mục a, sau đó xử lý danh sách tệp của thư mục b, phát hiện cũng có các tệp cần xóa b1-b3, liền tay xóa chúng, tương tự c1-c3 cũng vậy.

Nếu là "--delete-delay", thì sau khi đồng bộ xong các thư mục a/b/c trong danh sách tệp, cuối cùng xóa một lần a1-a3, b1-b3, c1-c3.

Thực tế, tùy chọn "--delete" hầu hết các trường hợp mặc định sử dụng "--delete-during".

2.5 Chế độ rsync daemon


2.5.1 Giới thiệu đơn giản

Vì rsync đã có thể thực hiện đồng bộ tệp giữa hai máy chủ qua remote shell, tại sao còn cần sử dụng rsync service? Hãy tưởng tượng bạn có một đống tệp trên máy của mình cần đồng bộ định kỳ đến nhiều máy khác, ví dụ như thư mục a, b, c chuyên dùng để truyền đến máy chủ web, d/e, f, g/h chuyên dùng để truyền đến máy chủ ftp, còn cần loại trừ một số tệp trong các thư mục này, nếu sử dụng phương thức kết nối remote shell, dù là sử dụng quy tắc loại trừ hay quy tắc bao gồm, thậm chí truyền từng lệnh rsync một, đều không vấn đề, nhưng quá rườm rà và mỗi lần phải nhập cùng một lệnh quá cứng nhắc. Sử dụng rsync daemon có thể giải quyết vấn đề cứng nhắc này. Hơn nữa, rsync daemon là cung cấp dịch vụ ra bên ngoài, như vậy chỉ cần nói cho người khác đường dẫn url của rsync, người ngoài có thể lấy danh sách tệp như lấy tệp từ ftp server, vì vậy danh sách bạn lập, đồng nghiệp của bạn cũng có thể lấy và sử dụng.

Hãy lấy một ví dụ đơn giản, trang web chính thức của Linux kernel www.kernel.org cung cấp phương thức tải xuống rsync, địa chỉ chính thức mà họ đưa ra là rsync://rsync.kernel.org/pub, có thể dựa vào địa chỉ này tìm ra phiên bản kernel bạn muốn tải. Ví dụ, để tìm các tệp liên quan đến kernel phiên bản linux-3.0.15.

[root@xuexi ~]# rsync --no-motd -r -v -f "+ */" -f "+ linux-3.0.15*" -f "- *" -m rsync://rsync.kernel.org/pub/
receiving file list ... done
drwxr-xr-x         124 2017/07/14 20:27:22 .
drwxr-xr-x         178 2014/11/12 05:50:10 linux
drwxr-xr-x        4096 2017/06/27 05:46:27 linux/kernel
drwxr-xr-x      237568 2017/07/05 20:49:33 linux/kernel/v3.x
-rw-r--r--    76803806 2012/01/04 03:00:31 linux/kernel/v3.x/linux-3.0.15.tar.bz2
-rw-r--r--    96726195 2012/01/04 03:00:31 linux/kernel/v3.x/linux-3.0.15.tar.gz
-rw-r--r--         836 2012/01/04 03:00:31 linux/kernel/v3.x/linux-3.0.15.tar.sign
-rw-r--r--    63812604 2012/01/04 03:00:31 linux/kernel/v3.x/linux-3.0.15.tar.xz
 
sent 59 bytes  received 80.19K bytes  12.35K bytes/sec
total size is 237.34M  speedup is 2957.66

Bạn không cần quan tâm các quy tắc ở trên đại diện cho điều gì, cần tập trung vào điểm là thông qua rsync có thể cung cấp danh sách tệp ra bên ngoài và cung cấp chức năng tải xuống tương ứng.

Tương tự, bạn cũng có thể kéo các tệp trên rsync daemon về cục bộ để thực hiện chức năng tải xuống.

[root@xuexi ~]# rsync --no-motd -avzP rsync://rsync.kernel.org/pub/linux/kernel/v3.x/linux-3.0.15.tar.bz2 /tmp
receiving incremental file list
linux-3.0.15.tar.bz2
     2834426   3%   300.51kB/s    0:40:22

Bây giờ hãy giới thiệu rsync daemon.

rsync daemon là "rsync --daemon" hoặc thêm một số tùy chọn khác để khởi động, nó sẽ đọc tệp cấu hình, mặc định là /etc/rsyncd.conf, và mặc định lắng nghe trên cổng 873, khi có client kết nối đến cổng này, có thể hoàn thành kết nối thông qua socket mạng, sau đó tất cả dữ liệu giao tiếp với client sẽ được truyền qua socket này.

Phương thức giao tiếp và kênh truyền của rsync daemon khác với remote shell. Phương thức giao tiếp của remote shell là hai đầu kết nối qua ống, ngay cả khi một đầu là máy chủ từ xa, khi kết nối đến đích, sẽ fork ra tiến trình rsync trên đích dựa trên tiến trình remote shell để làm rsync server. Trong khi rsync daemon là tiến trình rsync chạy nền trên server (theo tùy chọn khởi động, cũng có thể đặt thành không chạy nền), nó lắng nghe socket và chờ kết nối từ client, sau khi kết nối được thiết lập, tất cả phương thức giao tiếp đều được thực hiện qua socket.

Lưu ý rằng, khái niệm server trong rsync chưa bao giờ đại diện cho rsync daemon, server trong rsync chỉ là một thuật ngữ chung, miễn là không phải là client khởi tạo yêu cầu rsync, thì đó là server, bạn có thể coi rsync daemon là một loại server đặc biệt, thực tế daemon nên được gọi là service. (Tại sao giải thích điều này, là để tránh các bạn mới học bị hiểu lầm khi đọc man rsync)

Dưới đây là cú pháp lệnh của client rsync kết nối với rsync daemon:

Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]
      rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
Push: rsync [OPTION...] SRC... [USER@]HOST::DEST
      rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST

Có hai loại lệnh kết nối, một loại là phong cách rsync sử dụng dấu hai chấm kép "rsync user@host::src dest", một loại là cú pháp url "rsync://user@host:port/src dest". Đối với lệnh kết nối theo phong cách rsync, nếu muốn chỉ định số cổng, cần sử dụng tùy chọn "--port".

Trong cú pháp trên, đường dẫn trên daemon, như user@host::src, src đại diện cho tên mô-đun, không phải đường dẫn thật trong hệ thống tệp. Về mô-đun trong rsync, tin rằng sau khi xem tệp cấu hình dưới đây sẽ biết ý nghĩa của nó.

2.5.2 Tệp cấu hình daemon rsyncd.conf

Mặc định "rsync --daemon" đọc tệp cấu hình là /etc/rsyncd.conf, trên một số phiên bản hệ thống có thể tệp này không tồn tại theo mặc định. Xem man rsyncd.conf để biết cấu hình rsyncd.conf. Dưới đây là một phần nội dung:

[root@xuexi ~]# cat /etc/rsyncd.conf
# /etc/rsyncd: configuration file for rsync daemon mode
 
# See rsyncd.conf man page for more options.
 
# configuration example:
 
# uid = nobody
# gid = nobody
# use chroot = yes
# max connections = 4
# pid file = /var/run/rsyncd.pid
# exclude = lost+found/
# transfer logging = yes
# timeout = 900
# ignore nonreadable = yes
# dont compress   = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2
 
# [ftp1]
#        path = /home/ftp
#        comment = ftp export area

Trong tệp cấu hình ví dụ trên, trước tiên định nghĩa một số tùy chọn toàn cục, sau đó định nghĩa [ftp1], phần được bao quanh bởi dấu ngoặc vuông "[ftp1]" chính là所谓的 mô-đun trong rsync, ftp1 là ID mô-đun, phải đảm bảo duy nhất, mỗi mô-đun phải định nghĩa một mục "path", path định nghĩa đường dẫn mà mô-đun đại diện, ví dụ như trong tệp cấu hình ví dụ này, nếu muốn yêu cầu mô-đun ftp1, thì trên client sử dụng "rsync user@host::ftp1", điều này có nghĩa là truy cập /home/ftp trên user@host, nếu muốn truy cập thư mục con www trong /home/ftp, thì "rsync user@host::ftp1/www".

Dưới đây là các mục cấu hình phổ biến, cũng có thể coi là một ví dụ cấu hình:

######### Cấu hình tham số toàn cục ##########
port=888    # Chỉ định cổng rsync. Mặc định 873
uid = rsync # Người dùng chạy rsync service, mặc định là nobody, chủ sở hữu tệp sau khi truyền thành công sẽ là uid này
gid = rsync # Nhóm chạy rsync service, mặc định là nobody, nhóm sở hữu tệp sau khi truyền thành công sẽ là gid này
use chroot = no # rsync daemon có chuyển đến thư mục path được chỉ định trước khi truyền và giam trong đó không
max connections = 200 # Chỉ định số lượng kết nối tối đa, 0 có nghĩa là không giới hạn
timeout = 300         # Đảm bảo rsync server không bao giờ chờ một client bị treo, 0 có nghĩa là chờ mãi mãi
motd file = /var/rsyncd/rsync.motd   # Thông điệp hiển thị khi client kết nối
pid file = /var/run/rsyncd.pid       # Chỉ định tệp pid của rsync daemon
lock file = /var/run/rsync.lock      # Chỉ định tệp khóa
log file = /var/log/rsyncd.log       # Chỉ định tệp nhật ký của rsync, thay vì gửi nhật ký cho syslog
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2  # Chỉ định các tệp nào không cần nén khi truyền
 
########### Dưới đây chỉ định mô-đun, và đặt các tham số cấu hình mô-đun, có thể tạo nhiều mô-đun ###########
[longshuai]        # ID mô-đun
path = /longshuai/ # Chỉ định đường dẫn của mô-đun này, tham số này phải được chỉ định. Trước khi khởi động rsync service, thư mục này phải tồn tại. Yêu cầu truy cập mô-đun của rsync thực chất là truy cập đường dẫn này.
ignore errors      # Bỏ qua một số thông tin lỗi IO
read only = false  # Chỉ định mô-đun này có thể đọc ghi không, tức là có thể tải lên tệp, false có nghĩa là có thể đọc ghi, true có nghĩa là chỉ đọc. Tất cả các mô-đun mặc định không thể tải lên
write only = false # Chỉ định mô-đun này có hỗ trợ tải xuống không, đặt thành true có nghĩa là client không thể tải xuống. Tất cả các mô-đun mặc định có thể tải xuống
list = false       # Khi client yêu cầu hiển thị danh sách mô-đun, mô-đun này có hiển thị không, đặt thành false thì mô-đun này là mô-đun ẩn. Mặc định true
hosts allow = 10.0.0.0/24 # Chỉ định các máy được phép kết nối đến mô-đun này, nhiều ip cách nhau bằng dấu cách hoặc đặt khoảng
hosts deny = 0.0.0.0/32   # Chỉ định các máy không được phép kết nối đến mô-đun này
auth users = rsync_backup # Chỉ định danh sách người dùng được phép kết nối đến mô-đun này, chỉ có người dùng trong danh sách mới có thể kết nối đến mô-đun, tên người dùng và mật khẩu tương ứng được lưu trong secrets file,
                          # ở đây sử dụng không phải là người dùng hệ thống, mà là người dùng ảo. Không đặt thì mặc định tất cả người dùng đều có thể kết nối, nhưng sử dụng kết nối ẩn danh
secrets file = /etc/rsyncd.passwd # Lưu trữ tên người dùng và mật khẩu trong danh sách auth users, mỗi dòng chứa một username:passwd. Vì "strict modes"
                                  # Mặc định là true, nên tệp này yêu cầu người dùng không phải rsync daemon không thể đọc ghi. Chỉ khi bật auth users mới có hiệu lực.
[xiaofang]    # Dưới đây định nghĩa mô-đun thứ hai
path=/xiaofang/
read only = false
ignore errors
comment = anyone can access

Lưu ý:

(1). Khi client đẩy lên server, chủ sở hữu và nhóm của tệp là uid và gid được chỉ định trong tệp cấu hình. Nhưng khi client kéo từ server, chủ sở hữu và nhóm của tệp là người dùng đang thực thi rsync trên client, vì người dùng thực thi chương trình rsync là người dùng hiện tại.

(2). auth users và secrets file hai dòng này không nhất thiết cần, bỏ qua chúng sẽ mặc định sử dụng kết nối ẩn danh. Nhưng nếu sử dụng chúng, thì quyền của tệp secrets file phải là 600. Tệp mật khẩu của client cũng phải là 600.

(3). Về quyền của tệp secrets file, thực tế không nhất thiết là 600, chỉ cần thỏa mãn người dùng chạy rsync daemon có thể đọc là được. Việc kiểm tra quyền được đặt bằng tùy chọn strict mode, nếu đặt thành false, thì không cần quan tâm đến quyền tệp. Nhưng mặc định là yes, tức là cần đặt quyền.

Sau khi cấu hình, tiếp theo là cung cấp thư mục liên quan đến mô-đun, tệp xác thực, v.v.

[root@xuexi ~]# useradd -r -s /sbin/nologin rsync

[root@xuexi ~]# mkdir /{longshuai,xiaofang}

[root@xuexi ~]# chown -R rsync.rsync /{longshuai,xiaofang}

Cung cấp tệp xác thực cho mô-đun longshuai, vì rsync daemon chạy với quyền root, nên yêu cầu tệp xác thực không thể đọc ghi bởi người dùng không phải root, vì vậy đặt quyền 600.

[root@xuexi ~]# echo "rsync_backup:123456" >> /etc/rsyncd.passwd

[root@xuexi ~]# chmod 600 /etc/rsyncd.passwd 

Sau đó khởi động rsync daemon, cách khởi động rất đơn giản.

[root@xuexi ~]# rsync --daemon

Nếu là CentOS 7, thì có sẵn script khởi động.

[root@xuexi ~]# systemctl start rsyncd

Xem nội dung của script này.

[root@xuexi ~]# cat /usr/lib/systemd/system/rsyncd.service
[Unit]
Description=fast remote file copy program daemon
ConditionPathExists=/etc/rsyncd.conf
 
[Service]
EnvironmentFile=/etc/sysconfig/rsyncd
ExecStart=/usr/bin/rsync --daemon --no-detach "$OPTIONS"
 
[Install]
WantedBy=multi-user.target

Có thể thấy cách khởi động cũng chỉ thêm một "--no-detach", tùy chọn này có nghĩa là rsync không tách khỏi terminal.

Tóm lại, sau khi khởi động rsync daemon, nó sẽ lắng nghe trên cổng được chỉ định, chờ client kết nối.

Vì mô-đun longshuai trong ví dụ trên đã cấu hình chức năng xác thực, nên khi client kết nối sẽ hỏi mật khẩu. Nếu không muốn nhập mật khẩu thủ công, có thể sử dụng tùy chọn "--password-file" để cung cấp tệp mật khẩu, tệp mật khẩu chỉ có dòng đầu tiên mới là mật khẩu được truyền, các dòng còn lại sẽ bị tự động bỏ qua.

Ví dụ trên client:

[root@xuexi ~]# echo "123456" > /tmp/rsync_passwd

Sau đó sử dụng tùy chọn "--password-file" để kết nối với mô-đun longshuai cần xác thực.

[root@xuexi ~]# echo "123456" > /tmp/rsync_passwd

Nếu cần truy cập một tệp trong mô-đun, thì:

[root@xuexi ~]# rsync --list-only --port 888 rsync_backup@172.16.l0.6::longshuai/a/b --password-file=/tmp/rsync_passwd

Cũng có thể sử dụng cú pháp định dạng url:

[root@xuexi ~]# rsync --list-only rsync://rsync_backup@172.16.l0.6:888/longshuai/a/b --password-file=/tmp/rsync_passwd

2.6 Kết nối sử dụng daemon qua remote shell


Ở trên đã nói rsync có ba cách làm việc: chế độ đồng bộ cục bộ, chế độ remote shell và chế độ rsync daemon. Hai cách đầu tiên là sử dụng ống để giao tiếp và truyền dữ liệu, cách thứ ba là sử dụng socket mạng để giao tiếp và truyền dữ liệu, và rsync daemon yêu cầu trên server phải đã chạy rsync và lắng nghe trên cổng chỉ định.

Nhưng rsync hỗ trợ cách làm việc thứ tư: kết nối rsync daemon qua remote shell. Tức là kết hợp cách thứ hai và thứ ba. Mặc dù cách này ít được sử dụng, nhưng vẫn cần giải thích một chút, để giúp bạn đọc man rsync.

Để tiện gọi, tạm gọi cách kết nối sử dụng daemon qua remote shell là "remote shell daemon", tất nhiên, không có thuật ngữ chính thức như vậy, chỉ là tôi gọi tạm để tiện.

Cách remote shell daemon thực chất là "phương thức giao tiếp remote shell + sử dụng chức năng rsync daemon". Vì vậy phương thức giao tiếp của nó giống với remote shell, trên client khởi tạo kết nối remote shell, trên server fork tiến trình remote shell để khởi động rsync tiến trình, nhưng tiến trình rsync này là rsync daemon tạm thời, nó chỉ đọc phần mô-đun được client yêu cầu trong tệp cấu hình, và chỉ đọc các nội dung liên quan đến đường dẫn và xác thực của mô-đun (tức là không tải các mục cấu hình toàn cục và các mục mô-đun khác vào bộ nhớ, các cấu hình khác dưới mô-đun này cũng không có hiệu lực), khi hoạt động rsync hoàn tất, rsync daemon tạm thời này sẽ biến mất và được dọn dẹp khỏi bộ nhớ. Hơn nữa, rsync daemon tạm thời được khởi động bởi remote shell không xung đột với rsync daemon đã chạy trên server, chúng có thể cùng tồn tại. Vì mục tiêu cuối cùng của kết nối remote shell là mô-đun rsync, nên nó chỉ có thể sử dụng cú pháp rsync daemon.

Dưới đây là cú pháp: để ngắn gọn, không chỉ định src hay dest, và lấy ssh làm remote shell làm ví dụ.

rsync [options] --rsh=ssh auth_user@host::module

rsync [options] --rsh="ssh -l ssh_user" auth_user@host::module

rsync [options] -e "ssh -l ssh_user" auth_user@host::module

rsync [options] -e "ssh -l ssh_user" rsync://auth_user@host/module

Liên quan đến hai người dùng ssh_user và auth_user, vì sử dụng phương thức giao tiếp remote shell, nên client cần thiết lập kết nối ssh với server, ssh_user là người dùng ssh kết nối server. auth_user là người dùng xác thực của mô-đun. Nếu không chỉ định "ssh_user", thì mặc định sẽ sử dụng auth_user, nhưng nhiều lúc auth_user chỉ là người dùng ảo, như vậy không thể thiết lập kết nối ssh dẫn đến thất bại, vì vậy nên chỉ định rõ ssh_user và auth_user.

Một ví dụ có thể giải thích tất cả ở trên. Dưới đây là cấu hình mô-đun trong tệp cấu hình /etc/rsyncd.conf trên server, sau đó sẽ yêu cầu mô-đun này từ client qua phương thức remote shell.

[tmpdir]
path=/tmp
auth users=lisi
secrets file=/tmp/lisi_passwd

Hiện tại server không có rsync daemon đang chạy.

[root@xuexi ~]# netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN    
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN    
tcp6       0      0 :::22                   :::*                    LISTEN    
tcp6       0      0 ::1:25                  :::*                    LISTEN

Trên client sử dụng lệnh sau:

[root@xuexi ~]# rsync --list-only -e "ssh -l root" lisi@172.16.10.6::tmpdir
root@172.16.10.6's password:
 
Password:

Có thể thấy yêu cầu nhập mật khẩu hai lần, lần đầu tiên là mật khẩu của root@XXX, tức là mật khẩu để thiết lập kết nối ssh, chỉ khi thiết lập được kết nối ssh, mới có thể khởi động rsync daemon tạm thời trên server. Lần thứ hai nhập mật khẩu Password là mật khẩu tương ứng với "auth users=lisi".

Thẻ: rsync file synchronization backup incremental backup remote shell

Đăng vào ngày 12 tháng 6 lúc 08:49