tar: tệp đã thay đổi khi chúng tôi đọc nó


77

Tôi đang sử dụng maketar để sao lưu. Khi thực hiện makefile, lệnh tar sẽ hiển thị file changed as we read it. Trong trường hợp này,

  • gói tar vẫn ổn khi cảnh báo xuất hiện
  • nhưng nó dừng lệnh tar để sao lưu sau
  • tệp hiển thị cảnh báo trên thực tế không thay đổi - thật kỳ lạ khi cảnh báo xuất hiện
  • các tệp hiển thị cảnh báo xuất hiện ngẫu nhiên, ý tôi là, mỗi khi tôi chạy makefile của mình, các tệp hiển thị cảnh báo sẽ khác nhau
  • --ignore-failed-readkhông giúp ích gì. Tôi đang sử dụng tar 1.23 trong MinGW
  • Tôi vừa đổi máy tính của mình thành WIN7 64 bit. Tập lệnh hoạt động tốt trong WIN7 32 bit cũ. Nhưng phiên bản tar không mới bằng phiên bản 1.23.

Làm cách nào để dừng cảnh báo của tar để dừng sao lưu sau cảnh báo?


Chỉnh sửa-2 : nó có thể là lý do

Như tôi đã nói ở trên, tập lệnh bash shell hoạt động tốt trong máy tính cũ của tôi. So sánh với máy tính cũ, msysphiên bản là khác nhau. Phiên bản của lệnh tar cũng vậy. Trong máy tính cũ, tar là 1.13.19 và trong máy tính mới là 1.23. Tôi đã sao chép lệnh tar cũ mà không sao chép msys-1.0.dll phụ thuộc của nó vào máy tính mới và đổi tên thành tar_old. Và tôi cũng đã cập nhật lệnh tar trong shell script và chạy script. Sau đó, mọi thứ là ok. Vì vậy, có vẻ như vấn đề là lệnh tar. Tôi chắc chắn rằng không có bất kỳ tệp nào bị thay đổi khi gắn thẻ. Nó có phải là một lỗi cho lệnh tar trong phiên bản mới? Tôi không biết.


Chỉnh sửa-1 : thêm các chi tiết khác

Bản sao lưu được gọi bởi một tập lệnh bash shell. Nó quét thư mục đích và xây dựng makefile sau đó gọi lệnh make sử dụng tar để sao lưu. Tiếp theo là một makefile điển hình được xây dựng bởi bash shell script.

#--------------------------------------------
# backup VC
#--------------------------------------------
# the program for packing
PACK_TOOL=tar

# the option for packing tool
PACK_OPTION=cjvf

# M$: C driver
WIN_C_DIR=c:

# M$: D driver
WIN_D_DIR=d:

# M$: where the software is
WIN_PRG_DIR=wuyu/tools
# WIN_PRG_DIR=

# where to save the backup files
BAKDIR=/home/Wu.Y/MS_bak_MSYS

VC_FRAMEWORK=/home/Wu.Y/MS_bak_MSYS/tools/VC/VC_framework.tar.bz2
VC_2010=/home/Wu.Y/MS_bak_MSYS/tools/VC/VC_2010.tar.bz2

.PHONY: all

all: $(VC_FRAMEWORK) $(VC_2010)

$(VC_FRAMEWORK): $(WIN_C_DIR)/$(WIN_PRG_DIR)/VC/Framework/*
    @$(PACK_TOOL) $(PACK_OPTION) "$@" --ignore-failed-read /c/$(WIN_PRG_DIR)/VC/Framework
$(VC_2010): $(WIN_C_DIR)/$(WIN_PRG_DIR)/VC/VS2010/*
    @$(PACK_TOOL) $(PACK_OPTION) "$@" --ignore-failed-read /c/$(WIN_PRG_DIR)/VC/VS2010

Như bạn có thể thấy, gói tar được lưu trữ trong ~ / MS_bak_MSYS / tools / VC / VC_2010.tar.bz2. Tôi chạy tập lệnh trong ~ / qqaa. ~/MS_bak_MSYSbị loại trừ khỏi lệnh tar. Vì vậy, tệp tar mà tôi đang tạo không nằm trong thư mục mà tôi đang cố gắng đưa vào tệp tar. Đây là lý do tại sao tôi cảm thấy kỳ lạ khi cảnh báo xuất hiện.


Có vẻ như bạn đang sử dụng thiết lập cửa sổ nên không phù hợp với bạn. Tuy nhiên, chúng tôi gặp vấn đề tương tự khi hệ thống tệp cơ bản là glusterfs. Dường như có một lỗi khi lstat và trở fstat giá trị khác nhau: bugzilla.redhat.com/show_bug.cgi?id=1058526
Arie Skliarouk

Gặp sự cố này bằng cách sử dụng tar trên một ổ đĩa được gắn bởi windows docker. Trao đổi các tartiện ích paxlàm việc cho tôi.
Andreas

Câu trả lời:


78

Tôi cũng gặp phải các thông báo tar "đã thay đổi khi chúng tôi đọc nó". Đối với tôi, thông báo này xảy ra khi tôi đang tạo tệp tar của hệ thống tệp Linux trong môi trường xây dựng bitbake. Lỗi này là rời rạc.

Đối với tôi, điều này không phải do tạo tệp tar từ cùng một thư mục. Tôi giả sử thực sự có một số tệp bị ghi đè hoặc thay đổi trong quá trình tạo tệp tar.

Thông báo là một cảnh báo và nó vẫn tạo ra tệp tar. Chúng tôi vẫn có thể chặn các thông báo cảnh báo này bằng cách cài đặt tùy chọn

--warning=no-file-changed

( http://www.gnu.org/software/tar/manual/html_section/warnings.html )

Vẫn mã thoát do tar trả về là "1" trong trường hợp thông báo cảnh báo: http://www.gnu.org/software/tar/manual/html_section/Synopsis.html

Vì vậy, nếu chúng ta đang gọi tệp tar từ một số hàm trong tập lệnh, chúng ta có thể xử lý mã thoát như sau:

set +e 
tar -czf sample.tar.gz dir1 dir2
exitcode=$?

if [ "$exitcode" != "1" ] && [ "$exitcode" != "0" ]; then
    exit $exitcode
fi
set -e

Tôi có cùng một vấn đề và câu trả lời này đã "giải quyết" vấn đề của tôi bằng cách cho tôi khả năng giải quyết vấn đề đó. Cảm ơn @sandeep.
jaskho

11
Tar thoát với 1: "Nếu tar được cung cấp tùy chọn` --create ', `--append' hoặc` --update ', mã thoát này có nghĩa là một số tệp đã bị thay đổi trong khi được lưu trữ và do đó, tệp lưu trữ kết quả không chứa chính xác bản sao của tập hợp tệp. " Đây là một hành vi xấu đáng kinh ngạc - nó sẽ giết chết một đường ống dẫn và không có cách nào để ngăn chặn nó. facepalm
Otheus

Lưu ý @Otheusset +e
Ryan Brodie

2
@RyanBrodie Tôi đã suy nghĩ về set -o pipefail; tar ... | gzip. Nhưng tôi rút lại; nó sẽ không giết toàn bộ đường ống, vì lối ra bị trì hoãn cho đến khi kết thúc thực thi.
Otheus

60

Mặc dù nó rất muộn nhưng gần đây tôi đã có cùng một vấn đề.

Vấn đề là do dir .đang thay đổi khi xyz.tar.gzđược tạo sau khi chạy lệnh. Có hai giải pháp:

Giải pháp 1: tar sẽ không phiền nếu kho lưu trữ được tạo trong bất kỳ thư mục nào bên trong .. Có thể có lý do tại sao không thể tạo kho lưu trữ bên ngoài vùng làm việc. Đã làm việc xung quanh nó bằng cách tạo một thư mục tạm thời để đặt kho lưu trữ dưới dạng:

mkdir artefacts
tar -zcvf artefacts/archive.tar.gz --exclude=./artefacts .
echo $?
0

Giải pháp 2: Cái này tôi thích. tạo tệp lưu trữ trước khi chạy tar:

touch archive.tar.gz
tar --exclude=archive.tar.gz -zcvf archive.tar.gz .
echo $?
0

6
Trong giải pháp 2, chỉ cần đặt --exclude=archive.tar.gztrước optiosn khác -zvcfvà nó thực sự hoạt động tốt.
Kaj Kandler

36

Nếu bạn muốn được trợ giúp gỡ lỗi một vấn đề như thế này, bạn cần cung cấp quy tắc thực hiện hoặc ít nhất là lệnh tar mà bạn đã gọi. Làm thế nào chúng ta có thể thấy lệnh bị sai nếu không có lệnh để xem?

Tuy nhiên, 99% trường hợp xảy ra lỗi như thế này có nghĩa là bạn đang tạo tệp tar bên trong một thư mục mà bạn đang cố gắng đưa vào tệp tar. Vì vậy, khi tar cố gắng đọc thư mục, nó tìm thấy tệp tar như một thành viên của thư mục, bắt đầu đọc và ghi nó ra tệp tar, và cứ như vậy giữa thời điểm nó bắt đầu đọc tệp tar và khi nó kết thúc. đọc tệp tar, tệp tar đã thay đổi.

Vì vậy, ví dụ như một cái gì đó như:

tar cf ./foo.tar .

Không có cách nào để "ngăn chặn" điều này, bởi vì nó không sai. Chỉ cần đặt tệp tar của bạn ở một nơi khác khi bạn tạo nó hoặc tìm một cách khác (sử dụng --excludehoặc bất cứ điều gì) để bỏ qua tệp tar.


Tôi đã thêm nhiều chi tiết hơn trong bài viết gốc. Hãy kiểm tra.
Warem

Dựa trên thông tin ở đây, tôi không biết có gì sai. Tuy nhiên, tôi biết rất ít về làm việc với Windows hoặc Cygwin ... Tôi biết rằng hệ thống tập tin Windows là nhiều khó khăn hơn để làm việc với WRT nhiều chương trình truy cập vào cùng một tập tin hơn là một hệ thống tập tin POSIX-based. Nhưng điều đó dường như không liên quan ngay đến tình huống của bạn. Tất cả những gì tôi có thể đề xuất là loại bỏ các @quy tắc của bạn và kiểm tra lệnh thực hiện đang in để đảm bảo nó chính xác và xem các tệp tar đang cố gắng tạo (xuất từ ​​tùy chọn v) để đảm bảo không có gì bí ẩn.
MadScientist

18

Đây là một lớp lót để bỏ qua trạng thái thoát tar nếu nó là 1. Không cần set +enhư trong tập lệnh của sandeep . Nếu trạng thái thoát tar là 0 hoặc 1, một lớp lót này sẽ trở lại với trạng thái thoát 0. Ngược lại, nó sẽ trở lại với trạng thái thoát 1. Điều này khác với tập lệnh của sandeep ở đó giá trị trạng thái thoát ban đầu được giữ nguyên nếu nó khác 1 .

tar -czf sample.tar.gz dir1 dir2 || [[ $? -eq 1 ]]


5

Để tăng cường một lớp lót của Fabian; chúng ta hãy nói rằng chúng ta chỉ muốn bỏ qua trạng thái thoát 1 nhưng để duy trì trạng thái thoát nếu nó là bất kỳ điều gì khác:

tar -czf sample.tar.gz dir1 dir2 || ( export ret=$?; [[ $ret -eq 1 ]] || exit "$ret" )

Điều này thực hiện mọi thứ mà tập lệnh của sandeep thực hiện, trên một dòng.


4

Chỉ cần sử dụng một thư mục bên ngoài cho đầu ra, đã giải quyết được vấn đề cho tôi.

sudo tar czf ./../31OCT18.tar.gz ./

1
Nếu đặt tar mới trong cùng một thư mục bạn đang nén, nó thay đổi lol
Daniel W.

0

Nó hoạt động với tôi bằng cách thêm thời gian chờ ngủ đơn giản là 20 giây. Điều này có thể xảy ra nếu thư mục nguồn của bạn vẫn đang viết. Do đó, hãy tạm dừng để quá trình sao lưu kết thúc và sau đó tar sẽ hoạt động tốt. Điều này cũng giúp tôi có được trạng thái thoát đúng.

sleep 20
tar -czf ${DB}.${DATE}.tgz ./${DB}.${DATE}

0

Tôi không chắc nó có phù hợp với bạn không nhưng tôi nhận thấy rằng điều đó tarkhông xảy ra trên các tệp đã thay đổi / xóa ở chế độ ống dẫn. Hiểu ý tôi chứ.

Tập lệnh thử nghiệm:

#!/usr/bin/env bash
set -ex
tar cpf - ./files | aws s3 cp - s3://my-bucket/files.tar
echo $?

Xóa các tệp ngẫu nhiên theo cách thủ công ...

Đầu ra:

+ aws s3 cp - s3://my-bucket/files.tar
+ tar cpf - ./files
tar: ./files/default_images: File removed before we read it
tar: ./files: file changed as we read it
+ echo 0
0

1
Điều này là do mã thoát bị bỏ qua bên trong đường ống theo mặc định. Và đó là một phương pháp hay để kích hoạt chúng trở lại bằng cách "set -o pipefail".
Sergey
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.