Hành vi của rsync với tập tin vẫn đang được viết?


12

Nếu Apache đang viết một tệp lớn và một công việc cron rsync chạy trên tệp đó, rsync có cố gắng sao chép tệp không?

Thí dụ

  • Apache-1: Có tệp lớn được ghi vào /var/www.
  • Apache-2: Bản sao của Apache-1. Cứ năm phút lại có cron chạy rsync để được /var/wwwđồng bộ hóa.

Câu trả lời:


20

Nếu Apache đang viết một tệp nào đó đến một nơi và chưa hoàn thành việc viết nó và sau đó rsync khởi động, rsyncsẽ sao chép bất cứ thứ gì đang ngồi ở đó.

Có nghĩa là nếu Apache là đối phó với một file 5MB, chỉ có 2MB được viết và rsyncđá trong, file 2MB một phần sẽ được sao chép. Vì vậy, tập tin đó có vẻ như là lỗi bị hỏng trên máy chủ đích.

Tùy thuộc vào kích thước của tệp bạn đang sử dụng, bạn có thể sử dụng --inplacetùy chọn rsyncđể thực hiện các thao tác sau:

Tùy chọn này thay đổi cách rsync chuyển tệp khi cần cập nhật dữ liệu của tệp: thay vì phương pháp mặc định tạo bản sao mới của tệp và di chuyển tệp vào vị trí khi hoàn tất, thay vào đó, rsync ghi dữ liệu cập nhật trực tiếp vào đích tập tin.

Lợi ích của việc này là nếu một tệp 5 MB chỉ có 2 MB được sao chép trong lần chạy đầu tiên, lần chạy tiếp theo sẽ nhận ở mức 2 MB và tiếp tục sao chép tệp cho đến khi có đủ 5 MB.

Điều tiêu cực là nó có thể tạo ra tình huống ai đó đang truy cập máy chủ web trong khi một tệp đang được sao chép và sau đó họ sẽ thấy một phần tệp. Theo ý kiến ​​của tôi, nó rsynchoạt động tốt nhất trong hành vi mặc định của nó là lưu trữ một tập tin vô hình trên mạng và sau đó di chuyển nó vào vị trí ngay lập tức. Nhưng --inplacetốt cho các tình huống trong đó các tệp lớn và các ràng buộc về băng thông có thể cản trở một tệp lớn dễ dàng được sao chép từ một hình vuông.

Điều đó nói rằng bạn làm điều này; nhấn mạnh là của tôi:

Cứ năm phút lại có cron chạy rsync

Vì vậy, tôi giả sử bạn có một số tập lệnh bash tại chỗ để quản lý công việc định kỳ này? Vâng, điều này rsynclà đủ thông minh để chỉ sao chép các tập tin cần được sao chép. Và nếu bạn có một kịch bản chạy cứ sau 5 phút thì nó xuất hiện, bạn đang cố gắng tránh rsyncbước lên nhau nếu nó diễn ra nhanh hơn. Có nghĩa là, nếu bạn chạy nó mỗi phút, có một rủi ro là một hoặc nhiều rsyncquá trình vẫn sẽ chạy do kích thước tệp hoặc tốc độ mạng và quá trình tiếp theo sẽ cạnh tranh với nó; một điều kiện đua xe.

Một cách để tránh điều này là bọc toàn bộ rsynclệnh của bạn trong tập lệnh bash để kiểm tra khóa tệp; dưới đây là một khung kịch bản bash nồi hơi tôi sử dụng cho các trường hợp như thế này.

Lưu ý rằng một số người sẽ khuyên bạn nên sử dụng flocknhưng vì flockchưa được cài đặt trên một số hệ thống nên tôi sử dụng và tôi nhảy giữa Ubuntu (có nó) và Mac OS X (không có) rất nhiều. Tôi sử dụng khung đơn giản này mà không gặp vấn đề thực sự nào:

LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'

if mkdir ${LOCK_DIR} 2>/dev/null; then
  # If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
  echo $$ > ${PID_FILE}

  echo "Hello world!"

  rm -rf ${LOCK_DIR}
  exit
else
  if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
    # Confirm that the process file exists & a process
    # with that PID is truly running.
    echo "Running [PID "$(cat ${PID_FILE})"]" >&2
    exit
  else
    # If the process is not running, yet there is a PID file--like in the case
    # of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
    rm -rf ${LOCK_DIR}
    exit
  fi
fi

Ý tưởng là cốt lõi chung, nơi tôi có phần mềm echo "Hello world!", nơi trung tâm của kịch bản của bạn. Phần còn lại của nó về cơ bản là một cơ chế khóa / logic dựa trên mkdir. Một lời giải thích tốt về khái niệm này nằm trong câu trả lời này :

mkdir tạo một thư mục nếu nó chưa tồn tại và nếu có, nó sẽ đặt mã thoát. Quan trọng hơn, nó thực hiện tất cả điều này trong một hành động nguyên tử duy nhất làm cho nó hoàn hảo cho kịch bản này.

Vì vậy, trong trường hợp rsyncquy trình của bạn , tôi khuyên bạn nên sử dụng tập lệnh này bằng cách thay đổi echolệnh thành lệnh của bạn rsync. Ngoài ra, thay đổi LOCK_NAMEthành một cái gì đó như RSYNC_PROCESSvà sau đó bạn là tốt để đi.

Giờ đây, với rsynctập lệnh này, bạn có thể thiết lập công việc định kỳ để chạy mỗi phút mà không có bất kỳ rủi ro nào về điều kiện đua trong đó hai hoặc nhiều rsyncquy trình đang chiến đấu để làm điều tương tự. Điều này sẽ cho phép bạn tăng tốc độ hoặc rsynccập nhật sẽ không loại bỏ được vấn đề của một phần tệp được chuyển, nhưng nó sẽ giúp tăng tốc quá trình tổng thể để toàn bộ tệp có thể được sao chép chính xác tại một số điểm.


1
Cảm ơn vì đã chỉ ra khả năng nhiều rsyncs đang chạy, đã không nghĩ về điều đó. Kịch bản âm thanh tuyệt vời. Tôi chỉ cố gắng hiểu các vấn đề về việc đồng bộ hóa một trang web cân bằng tải với rsync, và điều này dường như làm giảm bớt chúng. Phần thưởng tuyệt vời. Vẫn cảm thấy có thể đây là cách tiếp cận sai ... nhưng hãy xem :)
Louis Waweru

@Louis Chào mừng bạn! Ngoài ra, nếu bạn muốn giữ các thư mục đồng bộ dựa trên các thay đổi tệp ngay lập tức, tôi khuyên bạn nên xem xét sử dụng / điều chỉnh lsyncd. Nó cho phép bạn có các thư mục nóng trên YouTube, những người thực sự chú ý đến hoạt động trong đó và sau đó hành động trên các tệp đó khi có thay đổi. Tôi sử dụng rsyncrất nhiều như được nêu trong câu trả lời của mình, nhưng tôi sử dụng lsyncdcho các trường hợp yêu cầu một hình thức hành động không phải là cron / ngay lập tức hơn.
JakeGould

3

Có - và tệp có thể bị hỏng nếu rsync đang đọc tệp cùng lúc tệp đang được ghi.

Bạn có thể thử điều này: /unix//a/2558

Bạn cũng có thể viết kịch bản với lsof:

lsof /path/to file

Mã thoát 0 có nghĩa là tệp đang được sử dụng và mã thoát 1 có nghĩa là không có hoạt động nào trên tệp đó.


Tôi không thấy lý do tại sao tệp sẽ bị hỏng nếu rsync chỉ đọc nó
orestisf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.