Tại sao bạn sẽ cat / dev / null vào bất cứ điều gì?
Bạn sẽ làm điều đó để cắt bớt nội dung tệp trong khi vẫn giữ nguyên nút inode. Tất cả các chương trình mở tệp để đọc hoặc ghi sẽ không bị ảnh hưởng ngoài thực tế kích thước tệp sẽ được đặt lại về 0.
Một thay thế không có thật thường được tìm thấy là loại bỏ tệp sau đó tạo lại nó:
rm file
touch file
hoặc tương tự:
mv file file.old
gzip file.old
touch file
Vấn đề là các phương thức này không ngăn không cho tệp cũ được ghi bởi bất kỳ quy trình nào có tệp bị xóa mở tại thời điểm xóa. Lý do tại sao trong hệ thống tệp Unix, khi bạn xóa một tệp, bạn chỉ hủy liên kết tên (đường dẫn) của nó khỏi nội dung của nó (inode). Inode được duy trì miễn là có các quá trình mở để đọc hoặc viết.
Điều này dẫn đến một số hiệu ứng tiêu cực: nhật ký được viết sau khi xóa tệp bị mất do không có cách đơn giản / di động để mở tệp bị xóa. Miễn là một quá trình ghi vào tệp bị xóa, nội dung của nó vẫn đang sử dụng không gian trên hệ thống tệp. Điều đó có nghĩa là nếu bạn xóa / tạo tệp vì nó đang lấp đầy đĩa của bạn, thì đĩa vẫn được lấp đầy. Một cách để khắc phục vấn đề sau này là khởi động lại các quy trình logger nhưng bạn có thể không muốn làm điều đó cho các dịch vụ quan trọng và nhật ký trung gian sẽ bị mất hoàn toàn. Ngoài ra còn có các tác dụng phụ do thực tế tệp bạn tạo có thể không có cùng quyền, chủ sở hữu và nhóm so với tệp gốc. Ví dụ, điều này có thể ngăn trình phân tích nhật ký đọc tệp mới tạo hoặc tệ hơn là ngăn quá trình ghi nhật ký ghi nhật ký của chính nó.
Phương pháp đầu tiên, cat /dev/null > file
đạt được mục tiêu đúng cách , tuy nhiên, mặc dù có một truyền thuyết đô thị ngoan cường, cat /dev/null
phần của nó hoàn toàn không có gì hữu ích. Nó mở một tệp giả mà trống theo thiết kế, nó không đọc được gì từ nó và cuối cùng chỉ thoát ra. Sử dụng lệnh này sau đó là lãng phí tổ hợp phím, byte, cuộc gọi hệ thống và chu kỳ CPU và nó có thể được thay thế mà không có bất kỳ thay đổi chức năng nào bằng lệnh no-op nhanh hơn :
hoặc thậm chí, với hầu hết các shell, không có lệnh nào cả.
Hãy để tôi thử một phép ẩn dụ để giải thích sự vô dụng như thế nào cat /dev/null
. Hãy nói rằng mục tiêu của bạn là làm trống một ly.
Trước tiên, bạn loại bỏ bất kỳ chất lỏng từ nó. Điều đó là đủ và chính xác là những gì ( > file
) đưa ra trong thực tế các chuyển hướng luôn được xử lý trước.
Sau đó, bạn chọn một chai rỗng ( /dev/null
) và đổ nó vào ly rỗng ( cat
). Đây là bước vô nghĩa ...
Nếu bạn đọc tài liệu được liên kết của bạn đến cuối, bạn có thể nhận thấy các nhận xét trong dòng này từ phiên bản nâng cao của tập lệnh:
cat / dev / null> wtmp # ':> wtmp' và '> wtmp' có cùng tác dụng.
Họ thực sự có; quá xấu cat /dev/null
đã được giữ trong mã.
Điều đó có nghĩa là đoạn mã sau sẽ hoạt động với tất cả các shell thông thường (cả csh
và sh
gia đình):
cd /var/log
: > messages
: > wtmp
echo "Log files cleaned up."
và điều này sẽ làm việc với tất cả các vỏ bằng cách sử dụng cú pháp Bourne, như ash
, bash
, ksh
, zsh
và những cái tên như:
cd /var/log
> messages
> wtmp
echo "Log files cleaned up."
Tuy nhiên, xin lưu ý rằng với các shell Bourne tiền POSIX cổ, bất kỳ lệnh nào trong số này, bao gồm cat /dev/null
sẽ không cắt bớt một tệp nếu nó được viết bởi một tập lệnh shell vẫn đang chạy vào nó. Thay vì một tệp 0 byte, đó sẽ là một tệp thưa thớt với kích thước không thay đổi. Điều tương tự sẽ xảy ra nếu tệp được viết bởi một quá trình tìm kiếm đến vị trí mà nó nghĩ là vị trí hiện tại trước khi viết.
Cũng cần lưu ý rằng một số giải pháp thay thế thường được đề xuất để cắt bớt một tập tin có sai sót.
Cả hai điều sau đây không làm được việc. Tệp kết quả không trống nhưng chứa một dòng trống. Điều này sẽ phá vỡ các tệp nhật ký như wtmp
lưu trữ các bản ghi chiều rộng cố định.
echo > file
echo "" > file
Tùy chọn tiếp theo dựa trên sh
tùy chọn BSD không khả dụng, POSIX không chỉ định bất kỳ tùy chọn được phép nào cho tiếng vang để bạn có thể kết thúc bằng một tệp có chứa một dòng có " -n
":
echo -n > file
Cái đó không thể mang theo được bằng cách sử dụng sh
chuỗi thoát System V. Một số shell sẽ tạo một tệp chứa một dòng có " \c
":
echo "\c" > file
Đó là một lệnh được thiết kế để thực hiện công việc. Vấn đề đang sử dụng truncate
là không khả dụng vì lệnh này, không được chỉ định bởi POSIX, có thể bị thiếu trong hệ thống Unix / Linux.
truncate -s 0
Cuối cùng, đây là một vài lựa chọn thay thế có thể mang theo và sẽ thực hiện đúng công việc: