Tìm các tệp mà người dùng có thể viết, hiệu quả với quá trình tạo tối thiểu


20

Tôi là người gốc. Tôi muốn biết liệu một người dùng không root có quyền truy cập ghi vào một số tệp hay không - hàng ngàn tệp. Làm thế nào để làm điều đó một cách hiệu quả trong khi tránh quá trình tạo?


Hãy cho chúng tôi thấy những gì bạn thực sự làm!
F. Hauri

Câu hỏi tương tự như unix.stackexchange.com/a/88591
Stéphane Chazelas

Giả sử bạn không quan tâm đến các điều kiện cuộc đua, tại sao không gọi access(2)bằng một UID thực được đặt một cách thích hợp (ví dụ: thông qua setresuid(2)hoặc tương đương di động)? Ý tôi là, tôi rất khó để làm điều đó từ bash, nhưng tôi chắc chắn Perl / Python có thể xử lý nó.
Kevin

1
@Kevin, shell ' [ -wthường sử dụng quyền truy cập (2) hoặc tương đương. Bạn cũng cần đặt các gids ngoài uid (như su hoặc sudo do). Bash không có hỗ trợ dựng sẵn cho điều đó nhưng zsh thì có.
Stéphane Chazelas

@ StéphaneChazelas - bạn có thể sử dụng chgrptrong mọi vỏ.
mikeerv

Câu trả lời:


2

Có lẽ như thế này:

#! /bin/bash

writable()
{
    local uid="$1"
    local gids="$2"
    local ids
    local perms

    ids=($( stat -L -c '%u %g %a' -- "$3" ))
    perms="0${ids[2]}"

    if [[ ${ids[0]} -eq $uid ]]; then
        return $(( ( perms & 0200 ) == 0 ))
    elif [[ $gids =~ (^|[[:space:]])"${ids[1]}"($|[[:space:]]) ]]; then
        return $(( ( perms & 020 ) == 0 ))
    else
        return $(( ( perms & 2 ) == 0 ))
    fi
}

user=foo
uid="$( id -u "$user" )"
gids="$( id -G "$user" )"

while IFS= read -r f; do
    writable "$uid" "$gids" "$f" && printf '%s writable\n' "$f"
done

Ở trên chạy một chương trình bên ngoài duy nhất cho mỗi tệp, cụ thể là stat(1).

Lưu ý: Điều này giả định bash(1)và sự hiện thân của Linux stat(1).

Lưu ý 2: Vui lòng đọc các nhận xét từ Stéphane Chazelas bên dưới để biết các nguy cơ và hạn chế tiềm ẩn trong quá khứ, hiện tại, tương lai và tiềm năng của phương pháp này.


Điều đó có thể nói rằng một tập tin có thể ghi được mặc dù người dùng không có quyền truy cập vào thư mục.
Stéphane Chazelas

Giả sử tên tệp không chứa ký tự dòng mới và đường dẫn tệp được truyền trên stdin không bắt đầu bằng -. Thay vào đó, bạn có thể sửa đổi nó để chấp nhận danh sách được phân định bằng NULread -d ''
Stéphane Chazelas

Lưu ý rằng không có thứ gọi là Linux . Linux là hạt nhân được tìm thấy trong một số hệ thống GNU và không GNU. Mặc dù có các lệnh (như từ util-linux) được viết riêng cho Linux, nhưng statbạn đang đề cập đến không phải, đó là lệnh GNU được chuyển đến hầu hết các hệ thống, không chỉ Linux. Cũng lưu ý rằng bạn đã có một statlệnh trên Linux từ lâu trước khi GNU statđược viết ( statnội dung zsh).
Stéphane Chazelas

2
@ Stéphane Chazelas: Lưu ý rằng không có thứ gọi là Linux. - Tôi tin rằng tôi đã viết "hóa thân của Linux stat(1)". Tôi đang đề cập đến một stat(1)chấp nhận -c <format>cú pháp, trái ngược với cú pháp BSD -f <format>. Tôi cũng tin rằng nó khá rõ ràng mà tôi đã không đề cập đến stat(2). Tôi chắc chắn rằng một trang wiki về lịch sử của các lệnh phổ biến sẽ khá thú vị.
lcd047

1
@ Stéphane Chazelas: Điều đó có thể nói rằng một tệp có thể ghi được mặc dù người dùng không có quyền truy cập vào thư mục chứa nó. - Đúng, và có lẽ là một giới hạn hợp lý. Giả sử tên tệp không chứa ký tự dòng mới - Đúng và có thể là giới hạn hợp lý. và đường dẫn tệp được truyền trên stdin không bắt đầu bằng - - Đã chỉnh sửa, cảm ơn bạn.
lcd047

17

TL; DR

find / ! -type l -print0 |
  sudo -u "$user" perl -Mfiletest=access -l -0ne 'print if -w'

Bạn cần hỏi hệ thống nếu người dùng có quyền ghi. Cách đáng tin cậy duy nhất là chuyển đổi các gid hiệu quả, gid và bổ sung hiệu quả sang người dùng và sử dụng lệnh access(W_OK)gọi hệ thống (thậm chí có một số hạn chế đối với một số hệ thống / cấu hình).

Và hãy nhớ rằng việc không có quyền ghi vào tệp không nhất thiết đảm bảo rằng bạn không thể sửa đổi nội dung của tệp tại đường dẫn đó.

Câu chuyện dài hơn

Chúng ta hãy xem xét những gì cần có để người dùng $ có quyền truy cập ghi /foo/file.txt(giả sử không có /foo/foo/file.txtlà liên kết tượng trưng)?

Anh ta cần:

  1. truy cập tìm kiếm/ (không cần read)
  2. truy cập tìm kiếm/foo (không cần read)
  3. viết quyền truy cập vào/foo/file.txt

Bạn có thể thấy các phương pháp tiếp cận (như @ lcd047's hoặc @ apaul's ) chỉ kiểm tra sự cho phép của file.txtsẽ không hoạt động vì họ có thể nói file.txtlà có thể ghi được ngay cả khi người dùng không có quyền tìm kiếm /hoặc /foo.

Và một cách tiếp cận như:

sudo -u "$user" find / -writeble

Sẽ không hoạt động vì nó sẽ không báo cáo các tệp trong thư mục mà người dùng không có quyền truy cập đọc (vì findđang chạy vì $userkhông thể liệt kê nội dung của họ) ngay cả khi anh ta có thể viết thư cho họ.

Nếu chúng ta quên ACL, hệ thống tệp chỉ đọc, cờ FS (như bất biến), các biện pháp bảo mật khác (apparmor, SELinux, thậm chí có thể phân biệt giữa các loại văn bản khác nhau) và chỉ tập trung vào các thuộc tính quyền và quyền sở hữu truyền thống, để có được cho phép (tìm kiếm hoặc viết), điều đó đã khá phức tạp và khó diễn đạt find.

Bạn cần:

  • nếu tệp thuộc sở hữu của bạn, bạn cần quyền đó cho chủ sở hữu (hoặc có uid 0)
  • nếu tệp không thuộc sở hữu của bạn, nhưng nhóm là của bạn, thì bạn cần có quyền đó cho nhóm (hoặc có uid 0).
  • nếu nó không thuộc sở hữu của bạn và không thuộc bất kỳ nhóm nào của bạn, thì các quyền khác sẽ được áp dụng (trừ khi uid của bạn bằng 0).

Theo findcú pháp, đây là một ví dụ với người dùng uid 1 và gids 1 và 2, đó sẽ là:

find / -type d \
  \( \
    -user 1 \( -perm -u=x -o -prune \) -o \
    \( -group 1 -o -group 2 \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) -o -type l -o \
    -user 1 \( ! -perm -u=w -o -print \) -o \
    \( -group 1 -o -group 2 \) \( ! -perm -g=w -o -print \) -o \
    ! -perm -o=w -o -print

Đó là một trong mận khô các thư mục mà người dùng không đã tìm kiếm phù hợp với và với nhiều loại file khác (symlink loại trừ như họ không có liên quan), kiểm tra để truy cập ghi.

Nếu bạn cũng muốn xem xét quyền truy cập ghi vào thư mục:

find / -type d \
  \( \
    -user 1 \( -perm -u=x -o -prune \) -o \
    \( -group 1 -o -group 2 \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) ! -type d -o -type l -o \
    -user 1 \( ! -perm -u=w -o -print \) -o \
    \( -group 1 -o -group 2 \) \( ! -perm -g=w -o -print \) -o \
    ! -perm -o=w -o -print

Hoặc cho một $userthành viên tùy ý và thành viên nhóm của nó được lấy từ cơ sở dữ liệu người dùng:

groups=$(id -G "$user" | sed 's/ / -o -group /g'); IFS=" "
find / -type d \
  \( \
    -user "$user" \( -perm -u=x -o -prune \) -o \
    \( -group $groups \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) ! -type d -o -type l -o \
    -user "$user" \( ! -perm -u=w -o -print \) -o \
    \( -group $groups \) \( ! -perm -g=w -o -print \) -o \
    ! -perm -o=w -o -print

(đó là 3 quá trình trong tổng số: id, sedfind)

Điều tốt nhất ở đây là hạ cây dưới dạng root và kiểm tra các quyền như người dùng cho mỗi tệp.

 find / ! -type l -exec sudo -u "$user" sh -c '
   for file do
     [ -w "$file" ] && printf "%s\n" "$file"
   done' sh {} +

(đó là một findquá trình cộng với một sudoshxử lý cứ sau vài nghìn tệp [printfthường được xây dựng trong trình bao).

Hoặc với perl:

find / ! -type l -print0 |
  sudo -u "$user" perl -Mfiletest=access -l -0ne 'print if -w'

(3 quá trình trong tổng số: find, sudoperl).

Hoặc với zsh:

files=(/**/*(D^@))
USERNAME=$user
for f ($files) {
  [ -w $f ] && print -r -- $f
}

(Tổng số 0 quá trình, nhưng lưu trữ toàn bộ danh sách tệp trong bộ nhớ)

Những giải pháp dựa trên access(2)cuộc gọi hệ thống. Đó là thay vì sao chép thuật toán mà hệ thống sử dụng để kiểm tra quyền truy cập, chúng tôi yêu cầu hệ thống thực hiện kiểm tra đó với cùng một thuật toán (có tính đến quyền tài khoản, ACL, cờ bất biến, hệ thống tệp chỉ đọc ... ) nó sẽ sử dụng nếu bạn cố gắng mở tệp để viết, vì vậy đây là lần gần nhất bạn sẽ có được một giải pháp đáng tin cậy.

Để kiểm tra các giải pháp được đưa ra ở đây, với các kết hợp khác nhau của người dùng, nhóm và quyền, bạn có thể làm:

perl -e '
  for $u (1,2) {
    for $g (1,2,3) {
      $d1="u${u}g$g"; mkdir$d1;
      for $m (0..511) {
        $d2=$d1.sprintf"/%03o",$m; mkdir $d2; chown $u, $g, $d2; chmod $m,$d2;
        for $uu (1,2) {
          for $gg (1,2,3) {
            $d3="$d2/u${uu}g$gg"; mkdir $d3;
            for $mm (0..511) {
              $f=$d3.sprintf"/%03o",$mm;
              open F, ">","$f"; close F;
              chown $uu, $gg, $f; chmod $mm, $f
            }
          }
        }
      }
    }
  }'

Thay đổi người dùng giữa 1 và 2 và nhóm betweem 1, 2 và 3 và giới hạn bản thân chúng tôi ở mức 9 bit thấp hơn của các quyền như đã tạo các tệp 9458694. Điều đó cho các thư mục và sau đó một lần nữa cho các tập tin.

Điều đó tạo ra tất cả các kết hợp có thể u<x>g<y>/<mode1>/u<z>g<w>/<mode2>. Người dùng có uid 1 và gids 1 và 2 sẽ có quyền truy cập ghi u2g1/010/u2g3/777nhưng không u1g2/677/u1g1/777.

Bây giờ, tất cả các giải pháp đó đều cố gắng xác định đường dẫn của tệp mà người dùng có thể mở để ghi, khác với đường dẫn mà người dùng có thể sửa đổi nội dung. Để trả lời câu hỏi chung chung hơn đó, có một số điều cần tính đến:

  1. $ user có thể không có quyền ghi vào /a/b/filenhưng nếu anh ta sở hữu file(và có quyền truy cập tìm kiếm /a/bvà hệ thống tệp không ở chế độ chỉ đọc và tệp không có cờ bất biến và anh ta có quyền truy cập hệ thống), sau đó anh ta sẽ có thể thay đổi các quyền của filevà cấp cho chính mình quyền truy cập.
  2. Điều tương tự nếu anh ta sở hữu /a/bnhưng không có quyền truy cập tìm kiếm vào nó.
  3. $ user có thể không có quyền truy cập /a/b/filevì anh ta không có quyền truy cập tìm kiếm /ahoặc /a/b, nhưng tệp đó có thể có một liên kết cứng /b/c/filechẳng hạn, trong trường hợp đó anh ta có thể sửa đổi nội dung /a/b/filebằng cách mở nó qua /b/c/fileđường dẫn của nó .
  4. Điều tương tự với gắn kết gắn kết . Ông không thể có quyền truy cập tìm kiếm để /a, nhưng /a/bcó thể ràng buộc gắn trong /c, vì vậy ông có thể mở filecho văn bản qua nó /c/filecon đường khác.
  5. Anh ta có thể không có quyền ghi /a/b/file, nhưng nếu anh ta có quyền truy cập ghi vào /a/banh ta có thể xóa hoặc đổi tên filetrong đó và thay thế bằng phiên bản của chính anh ta. Anh ta sẽ thay đổi nội dung của tập tin /a/b/filengay cả khi đó sẽ là một tập tin khác.
  6. Điều tương tự nếu anh ta có quyền truy cập ghi /a(anh ta có thể đổi tên /a/bthành /a/c, tạo một /a/bthư mục mới và một thư mục mới filetrong đó.

Để tìm các đường dẫn $usercó thể sửa đổi. Để giải quyết 1 hoặc 2, chúng tôi không thể dựa vào access(2)cuộc gọi hệ thống nữa. Chúng tôi có thể điều chỉnh find -permcách tiếp cận của mình để giả sử quyền truy cập vào thư mục hoặc ghi quyền truy cập vào tệp ngay khi bạn là chủ sở hữu:

groups=$(id -G "$user" | sed 's/ / -o -group /g'); IFS=" "
find / -type d \
  \( \
    -user "$user" -o \
    \( -group $groups \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) ! -type d -o -type l -o \
    -user "$user" -print -o \
    \( -group $groups \) \( ! -perm -g=w -o -print \) -o \
    ! -perm -o=w -o -print

Chúng tôi có thể giải quyết 3 và 4, bằng cách ghi lại số thiết bị và số inode hoặc tất cả các tệp $ user có quyền ghi và báo cáo tất cả các đường dẫn tệp có các số dev + inode đó. Lần này, chúng ta có thể sử dụng các access(2)phương pháp dựa trên đáng tin cậy hơn :

Cái gì đó như:

find / ! -type l -print0 |
  sudo -u "$user" perl -Mfiletest=access -0lne 'print 0+-w,$_' |
  perl -l -0ne '
    ($w,$p) = /(.)(.*)/;
    ($dev,$ino) = stat$p or next;
    $writable{"$dev,$ino"} = 1 if $w;
    push @{$p{"$dev,$ino"}}, $p;
    END {
      for $i (keys %writable) {
        for $p (@{$p{$i}}) {
          print $p;
        }
      }
    }'

5 và 6 thoạt nhìn phức tạp bởi tbit của các quyền. Khi được áp dụng trên các thư mục, đó là bit xóa bị hạn chế ngăn người dùng (những người khác không phải là chủ sở hữu của thư mục) xóa hoặc đổi tên các tệp mà họ không sở hữu (mặc dù họ có quyền truy cập ghi vào thư mục).

Ví dụ, nếu chúng ta quay lại ví dụ trước đó, nếu bạn có quyền truy cập ghi vào /a, thì bạn sẽ có thể đổi tên /a/bthành /a/c, sau đó tạo lại một /a/bthư mục và một thư mục mới filetrong đó. Nhưng nếu tbit được đặt /avà bạn không sở hữu /a, thì bạn chỉ có thể làm điều đó nếu bạn sở hữu /a/b. Điều đó mang lại:

  • Nếu bạn sở hữu một thư mục, theo 1, bạn có thể cấp cho mình quyền truy cập ghi và bit t không áp dụng (và dù sao bạn cũng có thể xóa nó), vì vậy bạn có thể xóa / đổi tên / tạo lại bất kỳ tệp hoặc thư mục nào trong đó, vì vậy tất cả các đường dẫn tệp bên dưới là của bạn để viết lại với bất kỳ nội dung.
  • Nếu bạn không sở hữu nó nhưng có quyền truy cập ghi, thì:
    • Hoặc tbit không được đặt và bạn ở trong trường hợp tương tự như trên (tất cả các đường dẫn tệp là của bạn).
    • hoặc nó được thiết lập và sau đó bạn không thể sửa đổi các tệp bạn không sở hữu hoặc không có quyền truy cập ghi, vì vậy với mục đích của chúng tôi là tìm đường dẫn tệp bạn có thể sửa đổi, điều đó giống như không có quyền ghi.

Vì vậy, chúng tôi có thể giải quyết tất cả 1, 2, 5 và 6 với:

find / -type d \
  \( \
    -user "$user" -prune -exec find {} + -o \
    \( -group $groups \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) ! -type d -o -type l -o \
    -user "$user" \( -type d -o -print \) -o \
    \( -group $groups \) \( ! -perm -g=w -o \
       -type d ! -perm -1000 -exec find {} + -o -print \) -o \
    ! -perm -o=w -o \
    -type d ! -perm -1000 -exec find {} + -o \
    -print

Đó và giải pháp cho 3 và 4 là độc lập, bạn có thể hợp nhất đầu ra của chúng để có được danh sách đầy đủ:

{
  find / ! -type l -print0 |
    sudo -u "$user" perl -Mfiletest=access -0lne 'print 0+-w,$_' |
    perl -0lne '
      ($w,$p) = /(.)(.*)/;
      ($dev,$ino) = stat$p or next;
      $writable{"$dev,$ino"} = 1 if $w;
      push @{$p{"$dev,$ino"}}, $p;
      END {
        for $i (keys %writable) {
          for $p (@{$p{$i}}) {
            print $p;
          }
        }
      }'
  find / -type d \
    \( \
      -user "$user" -prune -exec sh -c 'exec find "$@" -print0' sh {} + -o \
      \( -group $groups \) \( -perm -g=x -o -prune \) -o \
      -perm -o=x -o -prune \
    \) ! -type d -o -type l -o \
      -user "$user" \( -type d -o -print0 \) -o \
      \( -group $groups \) \( ! -perm -g=w -o \
         -type d ! -perm -1000 -exec sh -c 'exec find "$@" -print0' sh {} + -o -print0 \) -o \
      ! -perm -o=w -o \
      -type d ! -perm -1000 -exec sh -c 'exec find "$@" -print0' sh {} + -o \
      -print0
} | perl -l -0ne 'print unless $seen{$_}++'

Cần phải rõ ràng nếu bạn đã đọc mọi thứ cho đến nay, một phần của nó ít nhất chỉ liên quan đến quyền và quyền sở hữu, chứ không phải các tính năng khác có thể cấp hoặc hạn chế quyền truy cập ghi (chỉ đọc FS, ACL, cờ bất biến, các tính năng bảo mật khác ...). Và khi chúng tôi xử lý nó trong một số giai đoạn, một số thông tin đó có thể sai nếu các tệp / thư mục đang được tạo / xóa / đổi tên hoặc quyền / quyền sở hữu của chúng bị sửa đổi trong khi tập lệnh đó đang chạy, như trên một máy chủ tệp bận rộn với hàng triệu tệp .

Ghi chú tính di động

Tất cả mã đó là tiêu chuẩn (POSIX, Unix cho tbit) ngoại trừ:

  • -print0là một phần mở rộng GNU hiện cũng được hỗ trợ bởi một vài triển khai khác. Với các findtriển khai thiếu hỗ trợ cho nó, bạn có thể sử dụng -exec printf '%s\0' {} +thay thế và thay thế -exec sh -c 'exec find "$@" -print0' sh {} +bằng -exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +.
  • perlkhông phải là lệnh do POSIX chỉ định nhưng có sẵn rộng rãi. Bạn cần perl-5.6.0hoặc ở trên cho -Mfiletest=access.
  • zshkhông phải là lệnh do POSIX chỉ định. Đó zshmã trên nên làm việc với zsh-3 (1995) trở lên.
  • sudokhông phải là lệnh do POSIX chỉ định. Mã phải hoạt động với bất kỳ phiên bản nào miễn là cấu hình hệ thống cho phép chạy perlnhư người dùng đã cho.

Một là những gì tìm kiếm truy cập? Tôi chưa bao giờ nghe về nó trong các quyền truyền thống: đọc, viết, thực thi.
bela83

2
@ bela83, thực thi quyền trên một thư mục (bạn không thực thi các thư mục) dịch sang tìm kiếm . Đó là khả năng truy cập các tập tin trong đó. Bạn có thể liệt kê nội dung của thư mục nếu bạn có quyền đọc, nhưng bạn không thể làm bất cứ điều gì với các tệp trong đó trừ khi bạn cũng có quyền tìm kiếm ( xbit) trên thư mục. Bạn cũng có thể có quyền tìm kiếm nhưng không đọc , nghĩa là các tệp trong đó được ẩn cho bạn, nhưng nếu bạn biết tên của họ, bạn có thể truy cập chúng. Một ví dụ điển hình là thư mục tệp phiên php (đại loại như / var / lib / php).
Stéphane Chazelas

2

Bạn có thể kết hợp các tùy chọn với findlệnh, vì vậy nó sẽ tìm ra các tệp với chế độ và chủ sở hữu được chỉ định. Ví dụ:

$ find / \( -group staff -o -group users \) -and -perm -g+w

Lệnh trên sẽ liệt kê tất cả các mục thuộc về nhóm "nhân viên" hoặc "người dùng" và có quyền viết cho nhóm đó.

Bạn cũng nên kiểm tra các mục được sở hữu bởi người dùng của bạn và các tệp có thể ghi được trên thế giới, vì vậy:

$ find / \( -user yourusername -or \
             \(  \( -group staff -o -group users \) -and -perm -g+w \
             \) -or \
            -perm -o+w \
         \)

Tuy nhiên, lệnh này sẽ không khớp với các mục với ACL mở rộng. Vì vậy, susau đó bạn có thể tìm ra tất cả các mục có thể ghi:

# su - yourusername
$ find / -writable

Điều đó sẽ nói rằng một tập tin có r-xrwxrwx yourusername:anygrouphoặc r-xr-xrwx anyone:staffcó thể ghi.
Stéphane Chazelas

Nó cũng sẽ báo cáo là các tệp có thể ghi trong thư mục yourusernamekhông có quyền truy cập.
Stéphane Chazelas

1

Cách tiếp cận phụ thuộc vào những gì bạn đang thực sự thử nghiệm.

  1. Bạn có muốn đảm bảo truy cập ghi là có thể?
  2. Bạn có muốn đảm bảo thiếu quyền truy cập viết?

Điều này là do có rất nhiều cách để đến 2) và câu trả lời của Stéphane bao gồm những điều này tốt (không thể thay đổi là một điều cần nhớ), và nhớ lại rằng cũng có những phương tiện vật lý, chẳng hạn như ngắt kết nối ổ đĩa hoặc làm cho nó chỉ đọc ở cấp độ phần cứng (tab mềm). Tôi đoán hàng ngàn tệp của bạn nằm trong các thư mục khác nhau và bạn đang muốn báo cáo hoặc bạn đang kiểm tra danh sách chính. (Một sự lạm dụng khác của Puppet chỉ chờ để xảy ra).

Bạn có thể muốn truy cập cây perl của Stéphane và "tham gia" đầu ra với một danh sách nếu được yêu cầu (su cũng sẽ bắt thiếu thực thi trên các thư mục mẹ?). Nếu thay thế là một vấn đề hiệu suất, bạn đang làm điều này cho một "số lượng lớn" người dùng? Hay là một truy vấn trực tuyến? Nếu đây là một yêu cầu liên tục vĩnh viễn, có lẽ đã đến lúc xem xét một sản phẩm của bên thứ ba.


0

Bạn có thể làm...

find / ! -type d -exec tee -a {} + </dev/null

... Cho danh sách tất cả các tệp mà người dùng không thể ghi dưới dạng ghi vào thiết bị lỗi chuẩn ở dạng ...

"tee: cannot access %s\n", <pathname>" 

...hoặc tương tự.

Xem các bình luận bên dưới để biết các ghi chú về các vấn đề mà phương pháp này có thể có, và lời giải thích bên dưới về lý do tại sao nó có thể hoạt động. Sanely hơn, tuy nhiên, bạn nên có lẽ chỉ find các file thường xuyên thích:

find / -type f -exec tee -a {} + </dev/null

Nói tóm lại, teesẽ in lỗi khi nó cố gắng vào open()một tệp có một trong hai cờ ...

O_ HOÀN TOÀN

Chỉ mở để viết.

O_RDWR

Mở để đọc và viết. Kết quả là không xác định nếu cờ này được áp dụng cho một FIFO.

... và gặp ...

[EACCES]

Quyền tìm kiếm bị từ chối trên một thành phần của tiền tố đường dẫn hoặc tệp tồn tại và các quyền được chỉ định bởi oflag bị từ chối hoặc tệp không tồn tại và quyền ghi bị từ chối đối với thư mục mẹ của tệp được tạo hoặc O_TRUNC là quy định và cho phép viết bị từ chối.

... như được chỉ định ở đây :

Các teetiện ích có trách nhiệm sao chép đầu vào tiêu chuẩn để đầu ra tiêu chuẩn, làm cho một bản sao trong zero hoặc nhiều file. Các tiện ích tee không được đầu ra đệm.

Nếu -atùy chọn không được chỉ định, các tệp đầu ra sẽ được ghi (xem Đọc, ghi và tạo tệp ) ...

... POSIX.1-2008 yêu cầu chức năng tương đương với việc sử dụng O_APPEND ...

Bởi vì nó phải kiểm tra theo cách tương tự test -w...

-w tên đường dẫn

Đúng nếu tên đường dẫn phân giải thành một mục nhập thư mục hiện có cho một tệp cho phép ghi vào tệp sẽ được cấp, như được định nghĩa trong Đọc, ghi và tạo tệp . Sai nếu tên đường dẫn không thể được giải quyết hoặc nếu tên đường dẫn giải quyết mục nhập thư mục hiện có cho một tệp cho phép ghi vào tệp sẽ không được cấp.

Cả hai đều kiểm tra EACCESS .


Bạn có thể gặp phải giới hạn số lượng tệp được mở đồng thời với cách tiếp cận đó (trừ khi số lượng tệp thấp). Cảnh giác với các tác dụng phụ với các thiết bị và đường ống được đặt tên. Bạn sẽ nhận được một thông báo lỗi khác nhau cho ổ cắm.
Stéphane Chazelas 17/05/2015

@ StéphaneChazelas - Tất cả tue - Tôi nghĩ rằng nó cũng có thể đúng teesẽ bị treo trừ khi bị gián đoạn rõ ràng một lần mỗi lần chạy. Đó là điều gần nhất mà tôi có thể nghĩ đến [ -w... mặc dù vậy - đó là hiệu ứng nên gần gũi ở chỗ nó đảm bảo người dùng có thể OAPPEND tệp. Dễ dàng hơn nhiều so với tùy chọn sẽ là paxvới -ocác tùy chọn định dạng và / hoặc -tđể kiểm tra lại EACCESS- nhưng mỗi khi tôi đề nghị paxmọi người dường như nhún vai nó. Và, dù sao, thứ duy nhất paxtôi tìm thấy đáp ứng tiêu chuẩn đó là AST - trong trường hợp đó bạn cũng có thể sử dụng chúng ls.
mikeerv 17/05/2015
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.