Làm thế nào để kiểm tra không xâm lấn để truy cập ghi vào một tập tin?


20

Trong tập lệnh shell, làm thế nào để tôi dễ dàng và không xâm lấn kiểm tra quyền truy cập ghi vào tệp mà không thực sự cố gắng sửa đổi tệp?

Tôi có thể phân tích đầu ra của nó stat, nhưng điều đó có vẻ rất phức tạp và có lẽ dễ vỡ, mặc dù tôi không chắc sản lượng stat khác nhau bao nhiêu qua các lần thực hiện và thời gian.

Tôi có thể nối vào cuối tập tin và xem điều đó có thành công hay không, nhưng điều đó có khả năng gây nguy hiểm, vì hai lý do tôi có thể nghĩ ra:

  1. Bây giờ tôi phải loại bỏ phần bổ sung và trong trường hợp một số quy trình khác ghi vào tệp, điều này ngay lập tức trở nên không tầm thường vì dòng của tôi không còn là dòng cuối cùng.
  2. Bất kỳ quá trình đọc tệp nào cũng có thể có các yêu cầu tùy ý về nội dung của tệp đó và tôi có thể đã phá vỡ ứng dụng đó.

Câu trả lời:


29

Chỉ cần sử dụng - wcờ của sự testtiện lợi:

[ -w /path/to/file ] && echo "writeable" || echo "write permission denied"

Lưu ý rằng nếu bạn sẽ ghi vào tệp sau này, vẫn có khả năng bạn sẽ không thể ghi vào tệp. Các tập tin có thể đã di chuyển, các quyền có thể đã thay đổi, vv Nó cũng có thể -wphát hiện các quyền ghi nhưng một số yếu tố khác can thiệp để làm cho tập tin không thể ghi .


1
Tất nhiên! Tôi nên nghĩ rằng để kiểm tra trang người đàn ông của thử nghiệm. Cảm ơn bạn.
user50849

1
@qweilun nó là một shell dựng sẵn, nhưng bạn có thể hiển thị trang man thông qua man testhoặcman [
hỗn loạn

5
@chaos Nó là cả shell dựng và thực thi bên ngoài - thửtype -a
Volker Siegel

1
Theo nguồntest sử dụng euidaccessmà chỉ cần kiểm tra các bit cho phép . Không có các yếu tố khác (ví dụ: SELinux) có thể cấm truy cập ghi?
quả óc chó

2
@BroSlow, &&||có quyền ưu tiên như nhau. Họ được đánh giá từ trái sang phải.
tự đại diện

11

Cách tiếp cận khác:

if >> /path/to/file
then
    echo "writeable"
else
    echo "write permission denied"
fi

Điều này sẽ cố gắng mở tệp để nối thêm và nếu thành công, sẽ không chạy lệnh nào (nghĩa là chạy lệnh null ) với đầu ra cho tệp. 

Coi chừng việc này tạo ra một tệp trống nếu nó không tồn tại.

Các -w nhà điều hành của các testlệnh chỉ có thể làm một stat và sau đó cố gắng tìm hiểu xem có vẻ như bạn cần có quyền truy cập. Sự thay thế của tôi (ở trên) đáng tin cậy hơn so với testcách tiếp cận trong một số điều kiện đặc biệt, bởi vì nó buộc kiểm tra truy cập phải được thực hiện bởi kernel chứ không phải shell. Ví dụ,

  • nếu tệp nằm trên hệ thống tệp không phải Unix - đặc biệt nếu tệp được gắn từ xa từ máy chủ tệp không phải Unix - vì statcó thể trả về giá trị chế độ gây hiểu nhầm.
  • nếu tệp nằm trên một hệ thống tệp được gắn ở chế độ chỉ đọc.
  • nếu tệp có ACL và chế độ làm cho nó trông giống như bạn nên có quyền truy cập, nhưng ACL từ chối hoặc ngược lại.
  • nếu một số khung bảo mật (AppArmor, SELinux, tầm) từ chối quyền truy cập vào tệp.

3
Tôi mới thử cái này (trên Debian). Không có thời gian nào bị thay đổi, và đó là cách nó sẽ hoạt động trên bất kỳ Unix nào. Thời gian truy cập chỉ được cập nhật nếu bạn đọc từ tệp, thời gian sửa đổi chỉ được cập nhật nếu bạn ghi vào tệp. Mã này không. @Schwern: bạn có tài liệu tham khảo cho tuyên bố của mình không? Có ai đã thử chưa?
G-Man nói 'Phục hồi Monica'

2
PS @muru: Tôi mới thử touchmột tập tin mà tôi sở hữu nhưng không có quyền truy cập bằng văn bản và nó đã thành công. Tôi đoán đó chmodlà tập tin và chmodnó trở lại. Vì vậy, touchdường như là hoàn toàn vô dụng như là một câu trả lời cho câu hỏi.
G-Man nói 'Phục hồi Monica'

2
@ G-Man ah, thật thú vị. IIRC vimcó hành vi thay đổi nhanh chóng các quyền khi bị buộc phải ghi trên các tệp chỉ đọc. Tôi đã kiểm tra với strace, touch's openkhông thành công với EACCES, nhưng gọi tiếp theo để utimensatthành công, đó là lý do tại sao tôi nghĩ rằng touchtrên toàn bộ lối ra thành công.
muru

2
@muru: Cảm ơn bạn đã kiểm tra điều đó. utimensat(2)nói, các yêu cầu của Quyền Quyền: 1. quyền truy cập ghi (hoặc) 2. ID người dùng hiệu quả của người gọi phải phù hợp với chủ sở hữu của tệp,
G-Man nói 'Phục hồi' '

3
Các vấn đề khác như đối với Champignac's: >> filekhông khả dụng (ví dụ: chạy NULLCMD trong zsh), true >> filethay vào đó hãy sử dụng . Và nếu tập tin là một ống có tên, nó có tác dụng phụ khó chịu.
Stéphane Chazelas

3

G-man nói đúng: [ -w ]sẽ không luôn luôn nói sự thật. Ở đây để đối phó với tệp không tồn tại và thông báo Từ chối quyền từ shell:

( [ -e /path/to/file ] && >> /path/to/file ) 2> /dev/null && 
  echo writable || 
  echo not writable

Cập nhật : Có vẻ đáng sợ, phải không? Vâng, nó là. Hmm ... làm thế nào để diễn đạt nó ... KHÔNG SỬ DỤNG NÀY, trừ khi bạn hoàn toàn biết bạn đang ở trong điều kiện mà nó yêu cầu để làm việc như mong đợi. Xem bình luận của Stephane.

Những gì để kết luận, sau đó? Ngay cả khi [ -w ]không nói sự thật, đó là một lệnh được dự định để thực hiện công việc. Nếu không, tốt, chúng tôi sẽ đổ lỗi cho nó, viết báo cáo lỗi và nó sẽ hoạt động trong tương lai. Kiểm tra tốt hơn các điều kiện mà nó hoạt động và sử dụng [ -w ]; viết mã đặc biệt cho các trường hợp đặc biệt. Cách giải quyết có điều kiện riêng.

[ -w /path/to/file ]

một tiên nghiệm tốt nhất .


3
Nếu tệp là một ống có tên, nó sẽ bị treo nếu không đọc và ngay cả khi có một trình đọc sẽ có tác dụng phụ khó chịu. test -wtrong hầu hết các triển khai sử dụng access(2)nên phải đủ để kiểm tra quyền.
Stéphane Chazelas
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.