phục hồi tập tin bị xóa giữ bởi apache?


10

Giả sử một tệp nhật ký apache bị xóa nhưng nó được mở bằng apache; thì đây là những gì tôi đang làm:

pid=$(lsof | grep text.txt | awk '/deleted/ {print $2}')
fd=$(lsof | grep text.txt | awk '/deleted/ {print $4}' | grep -oE "[[:digit:]]{1,}")

cp /proc/$pid/fd/$fd directorytobecopied/testfile.txt

Đây là những gì tôi đang làm để khôi phục tập tin và đặt nó trở lại vị trí cũ. Có cách nào đơn giản hơn để làm điều này không vì mã trên không đẹp. Hơn nữa, làm thế nào để tôi biết nơi tệp bị xóa ( thư mục đã được xóa ) để tôi không phải hỏi thủ công ai đó nơi tệp được đặt nguyên bản và đặt nó trở lại đó.


lsof / | awk '(/deleted/||/abc.txt/) {print "FD :-",$4,"| File Name:-",$9}'
Rahul Patil

Câu trả lời:


14

Nếu một tập tin đã bị xóa nhưng vẫn còn mở, có nghĩa là các tập tin vẫn còn tồn tại trong hệ thống tập tin (nó có một inode ) nhưng có một liên kết cứng đếm 0. Vì không có liên kết đến tập tin, bạn không thể mở nó bằng tên . Không có cơ sở để mở một tập tin bằng inode.

Không có cách nào để khám phá tệp thông qua hệ thống tệp của nó và đặc biệt là không có cách nào để tìm tệp trong thư mục chứa nó. Các mục nhập thư mục đã biến mất. Tất cả những gì còn lại là tập tin chính nó. Bạn có thể truy cập tệp bằng trình gỡ lỗi hệ thống tệp, nhưng yêu cầu quyền root và khó sử dụng và dễ bị lỗi.

Linux hiển thị các tệp đang mở thông qua các liên kết tượng trưng đặc biệt dưới /proc. Các liên kết này được gọi /proc/12345/fd/42trong đó 12345 là PID của một quy trình và 42 là số lượng mô tả tệp trong quy trình đó. Một chương trình chạy cùng một người dùng với quá trình đó có thể truy cập tệp (các quyền đọc / ghi / thực thi giống như khi bạn xóa tệp).

Tên mà tệp được mở vẫn hiển thị trong mục tiêu của liên kết tượng trưng: nếu tệp là /var/log/apache/foo.log, thì mục tiêu của liên kết là /var/log/apache/foo.log (deleted). (Nếu tệp được đổi tên sau khi được mở, mục tiêu của liên kết tượng trưng có thể phản ánh việc đổi tên.)

Do đó, bạn có thể khôi phục nội dung của một tệp đã bị xóa được cung cấp cho PID của một quá trình mở nó và mô tả mà nó đã mở như thế này:

recover_open_deleted_file () {
  old_name=$(readlink "$1")
  case "$old_name" in
    *' (deleted)')
      old_name=${old_name%' (deleted)'}
      if [ -e "$old_name" ]; then
        new_name=$(TMPDIR=${old_name%/*} mktemp)
        echo "$oldname has been replaced, recovering content to $new_name"
      else
        new_name="$old_name"
      fi
      cat <"$1" >"$new_name";;
    *) echo "File is not deleted, doing nothing";;
  esac
}
recover_open_deleted_file "/proc/$pid/fd/$fd"

Nếu bạn chỉ biết ID tiến trình chứ không biết mô tả, bạn có thể khôi phục tất cả các tệp bằng

for x in /proc/$pid/fd/*; do
  recover_open_deleted_file "$x"
done

Nếu bạn không biết ID tiến trình, bạn có thể tìm kiếm trong số tất cả các quy trình:

for x in /proc/[1-9]*/fd/*; do
  case $(readlink "$x") in
    /var/log/apache/*) recover_open_deleted_file "$x";;
  esac
done

Bạn cũng có thể có được danh sách này bằng cách phân tích cú pháp đầu ra lsof, nhưng nó không đơn giản hơn cũng không đáng tin cậy hơn hay dễ mang theo hơn (dù sao đây cũng là đặc thù của Linux).


Bạn có thể mở / Proc / x / fd / y để đọc hoặc viết bất kể x có mở hay không để đọc hoặc viết.
Stéphane Chazelas

tại sao hệ điều hành unix cho phép xóa tệp khi nó mở ... trong khi chúng ta không thể thực hiện nó trong
windows

@munish Windows bắt đầu từ một mô hình đa nhiệm hợp tác: nếu một ứng dụng hoạt động sai, nó có thể khiến hệ thống bị hỏng. Hầu hết các vấn đề đã được khắc phục, nhưng Windows vẫn cho phép một ứng dụng chiếm quyền điều khiển một tệp: miễn là tệp được mở, nó không thể được đổi tên hoặc xóa. Unix không cho phép điều này: xóa hoặc đổi tên một tệp là trực giao khi mở nó.
Gilles 'SO- ngừng trở nên xấu xa'

1
Bạn vừa lưu nguồn gốc đối xứng của Muse cho tôi! Cảm ơn bạn hơn một ngàn lần!
dotancohen
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.