cp ghi đè vs rm rồi cp


18

Khi tôi cố gắng ghi đè lên một tập tin nhị phân mà hiện tại đang đưa ra, cpthất bại trong việc ghi đè lên, nhưng nó có thể để rmnó sau đó cp. Ví dụ:

user@poste:~$ cp binaryFile /tmp
user@poste:~$ sudo cp /tmp/binaryFile binaryFile 
[sudo] password for user:
cp: cannot create regular file `binaryFile`: Text file busy
user@poste:~$ sudo rm binaryFile 
user@poste:~$ sudo cp /tmp/binaryFile  binaryFile 
user@poste:~$ file binaryFile 
binaryFile : ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x7ce005d9eb50e2574246b6a881e625802f7e49f2, not stripped

Bất cứ ý tưởng tại sao?


2
Chủ đề nhỏ thú vị, nhưng nên có trên Unix / Linux.SE IMO.
gạch dưới

Câu trả lời:


41

Trong trường hợp đầu tiên, bạn đang cố ghi đè lên nội dung của tệp hiện đang chạy dưới dạng chương trình. Linux không cho phép điều đó - nếu có, bạn sẽ ghi đè mã ngay khi HĐH đang thực thi nó; sự khác biệt đầu tiên sẽ làm hỏng chương trình hoặc làm cho nó bị trục trặc.

Nhưng trong trường hợp thứ hai, bạn không thực sự thay đổi nội dung của tệp cũ - bạn đang tạo một tệp mới ở vị trí của nó, trong khi tệp cũ chỉ mất tên tệp mà vẫn giữ nguyên nội dung của tệp đó.

(Hãy nhớ rằng về mặt kỹ thuậtrm không xóa các tệp, nó chỉ xóa các liên kết thư mục - tương tự như cách thêm nhiều liên kết vào cùng một tệp. Chỉ khi một tệp không có liên kết không có tham chiếu tệp mở, nó sẽ tự động bị xóa.)ln

Hệ thống tham chiếu các tệp đang sử dụng bằng inode của chúng, vì vậy không có vấn đề gì khi chúng có cùng tên tệp - đó vẫn là tệp vẫn được hệ thống mở và mặc dù nó không còn liên kết nữa, nhưng nó sẽ chỉ bị xóa một khi tất cả các chương trình đóng nó.


7
Một mẹo khác thường được sử dụng bằng cùng một logic: Mở tệp (tạm thời) trong phần mềm của bạn và xóa nó ngay lập tức mà không đóng tệp trước. Chương trình của bạn vẫn có thể sử dụng nó theo bất kỳ cách nào nó muốn và khi chương trình của bạn đóng nó (được kiểm soát) hoặc quên đóng nó (ví dụ chương trình của bạn bị sập mà không dọn dẹp), hệ điều hành sẽ tự động bị xóa. (Kết thúc chương trình, bất kể điều đó xảy ra như thế nào, sẽ phát hành tất cả các tham chiếu đến chương trình vào tệp.)
Tonny

2
Đó cũng là lý do tại sao khi bạn xóa một số tệp nhật ký của một quy trình đang chạy, lệnh df sẽ không trả về kích thước đã sửa cho đến khi bạn dừng quá trình
M4rty

Có cách nào để một chương trình bên ngoài (với quyền riêng tư gốc) tìm và tạo một tay cầm mới cho nút inode lơ lửng này không? Tôi tưởng tượng có những chương trình sử dụng điều này như một "tính năng bảo mật" để thật thú vị khi hiểu toàn bộ câu chuyện.
BenPen

3
@BenPen: Trên Linux, có - sử dụng /proc/*/fdđể truy cập nó và tùy chọn linkat () để thêm một liên kết mới vào hệ thống tập tin.
grawity

3
@BenPen và grawity: Trên thực tế, bạn không thể liên kết một inode trở lại cấu trúc thư mục nếu nó không có liên kết, ngay cả với linkat(), vì lý do bảo mật . (Ngoại lệ cho quy tắc này: trừ khi nó được tạo bằng open(O_TMPFILE)vì vậy nó bắt đầu với các liên kết bằng không.) Nếu bạn thử, linkat()trả về ENOENT, ngay cả khi đã root. Xem câu trả lời của tôi cho câu hỏi đó để kịch bản perl thực sự chạy linkatvà chứng minh rằng nó không hoạt động, ngay cả khi đã root: /
Peter Cordes
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.