Finden Sie Dateien, die ein Benutzer mit minimaler Prozesserstellung effizient schreiben kann

20

Ich bin root Ich möchte wissen, ob ein Nicht-Root-Benutzer Schreibzugriff auf einige Dateien hat - Tausende von ihnen. Wie kann man effizient vorgehen und gleichzeitig die Erstellung von Prozessen vermeiden?

Howard
quelle
Bitte zeigen Sie uns, was Sie tatsächlich tun!
F. Hauri,
Dieselbe
Stéphane Chazelas
Angenommen, Sie interessieren sich nicht für die Rennbedingungen, warum rufen Sie nicht einfach access(2)mit einer entsprechend eingestellten realen UID an (z. B. über setresuid(2)oder das tragbare Äquivalent)? Ich meine, ich würde es schwer haben, das von Bash aus zu tun, aber ich bin mir sicher, dass Perl / Python damit umgehen kann.
Kevin
1
@ Kevin, Shells [ -wverwenden im Allgemeinen den Zugriff (2) oder einen gleichwertigen Wert . Sie müssen zusätzlich zu uid auch die Gids einstellen (wie su oder sudo). bash hat dafür keine eingebaute Unterstützung, zsh jedoch.
Stéphane Chazelas
@ StéphaneChazelas - Sie können chgrpin jeder Shell verwenden.
mikeserv

Antworten:

2

Vielleicht so:

#! /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

Das obige Programm führt für jede Datei ein einzelnes externes Programm aus, nämlich stat(1).

Hinweis: Dies setzt voraus bash(1), und die Linux-Inkarnation von stat(1).

Anmerkung 2: Bitte lesen Sie die nachstehenden Kommentare von Stéphane Chazelas zu Vergangenheit, Gegenwart, Zukunft und möglichen Gefahren und Einschränkungen dieses Ansatzes.

lcd047
quelle
Das könnte bedeuten, dass eine Datei beschreibbar ist, obwohl der Benutzer keinen Zugriff auf das Verzeichnis hat, in dem sie sich befindet.
Stéphane Chazelas
Dies setzt voraus, dass Dateinamen keine Zeilenumbrüche enthalten und die übergebenen Dateipfade nicht mit beginnen -. Man könnte es ändern , um eine NUL getrennte Liste zu akzeptieren , statt mitread -d ''
Stéphane Chazelas
Beachten Sie, dass es keine Linux-Statistik gibt . Linux ist der Kernel in einigen GNU- und Nicht-GNU-Systemen. Während es Befehle (wie from util-linux) gibt, die speziell für Linux geschrieben wurden, ist das, auf das statSie sich beziehen, kein GNU-Befehl, der auf die meisten Systeme portiert wurde, nicht nur auf Linux. Beachten Sie auch, dass Sie unter statLinux einen Befehl hatten, lange bevor GNU statgeschrieben wurde ( statzsh builtin).
Stéphane Chazelas
2
@ Stéphane Chazelas: Beachten Sie, dass es keine Linux-Statistik gibt. - Ich glaube, ich habe "die Linux-Inkarnation von stat(1)" geschrieben. Ich beziehe mich auf eine stat(1), die die -c <format>Syntax akzeptiert , im Gegensatz zu beispielsweise BSD-Syntax -f <format>. Ich glaube auch, dass es ziemlich klar war, dass ich mich nicht darauf bezog stat(2). Ich bin mir sicher, dass eine Wiki-Seite über die Geschichte der allgemeinen Befehle sehr interessant wäre.
lcd047
1
@ Stéphane Chazelas: Das könnte bedeuten, dass eine Datei beschreibbar ist, obwohl der Benutzer keinen Zugriff auf das Verzeichnis hat, in dem sie sich befindet. - Richtig und wahrscheinlich eine vernünftige Einschränkung. Dies setzt voraus, dass Dateinamen keine Zeilenumbrüche enthalten - Wahr und wahrscheinlich eine sinnvolle Einschränkung. und an stdin übergebene Dateipfade beginnen nicht mit - - Bearbeitet, danke.
lcd047
17

TL; DR

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

Sie müssen das System fragen, ob der Benutzer über Schreibrechte verfügt. Die einzig zuverlässige Möglichkeit besteht darin, die effektive Benutzer-ID, die effektive Benutzer-ID und die ergänzende Benutzer-ID auf die des Benutzers umzustellen und den access(W_OK)Systemaufruf zu verwenden (auch wenn dies bei einigen Systemen / Konfigurationen Einschränkungen aufweist).

Beachten Sie außerdem, dass das Fehlen einer Schreibberechtigung für eine Datei nicht unbedingt garantiert, dass Sie den Inhalt der Datei unter diesem Pfad nicht ändern können.

Die längere Geschichte

Lassen Sie uns überlegen , was es zum Beispiel für einen $ Benutzer nimmt Schreibzugriff zu haben , um /foo/file.txt(unter der Annahme keiner /foound /foo/file.txtSymlinks sind)?

Er braucht:

  1. Suche nach Zugang zu /(keine Notwendigkeit für read)
  2. Suche nach Zugang zu /foo(keine Notwendigkeit für read)
  3. Schreibzugriff auf/foo/file.txt

Sie können bereits sehen, dass Ansätze (wie @ lcd047 oder @ apaul ), die nur die Berechtigung von überprüfen file.txt, nicht funktionieren, weil sie sagen könnten, dass sie file.txtbeschreibbar sind, selbst wenn der Benutzer keine Suchberechtigung für /oder hat /foo.

Und ein Ansatz wie:

sudo -u "$user" find / -writeble

Funktioniert auch nicht, da keine Dateien in Verzeichnissen gemeldet werden, auf die der Benutzer keinen Lesezugriff hat (da findausgeführt wird, weil der $userInhalt nicht aufgelistet werden kann), selbst wenn er darauf schreiben kann.

Vergessen wir ACLs, schreibgeschützte Dateisysteme, FS-Flags (wie unveränderlich), andere Sicherheitsmaßnahmen (Apparmor, SELinux, die sogar zwischen verschiedenen Schreibweisen unterscheiden können) und konzentrieren wir uns nur auf traditionelle Berechtigungs- und Eigentumsattribute, um eine zu erhalten mit der erlaubnis (suchen oder schreiben) ist das schon ziemlich kompliziert und schwer auszudrücken find.

Du brauchst:

  • Wenn sich die Datei in Ihrem Besitz befindet, benötigen Sie diese Berechtigung für den Eigentümer (oder haben die UID 0).
  • Wenn sich die Datei nicht in Ihrem Besitz befindet, die Gruppe jedoch eine Ihrer ist, benötigen Sie diese Berechtigung für die Gruppe (oder haben die UID 0).
  • Wenn es Ihnen nicht gehört und keiner Ihrer Gruppen angehört, gelten die anderen Berechtigungen (es sei denn, Ihre UID ist 0).

In der findSyntax, hier als Beispiel mit einem Benutzer von UID 1 und GID 1 und 2, wäre das:

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

Dass man Pflaumen die Verzeichnisse der Benutzer suchen haben , nicht direkt für und für andere Arten von Dateien (Symlinks ausgeschlossen , da sie nicht relevant sind), Schecks für den Schreibzugriff.

Wenn Sie auch den Schreibzugriff auf Verzeichnisse in Betracht ziehen möchten:

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

Oder für eine beliebige $userund deren Gruppenmitgliedschaft, die aus der Benutzerdatenbank abgerufen wird:

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

(das ist 3 - Prozesse insgesamt: id, sedund find)

Am besten ist es, wenn Sie den Baum als root absteigen und die Berechtigungen als Benutzer für jede Datei prüfen.

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

(Das ist ein findProzess plus eins sudound shverarbeitet alle paar tausend Dateien [und printfwird normalerweise in der Shell erstellt.)

Oder mit perl:

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

(3 Prozesse insgesamt: find, sudound perl).

Oder mit zsh:

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

(0 Prozess insgesamt, speichert aber die gesamte Dateiliste im Speicher)

Diese Lösungen basieren auf dem access(2)Systemaufruf. Das heißt, anstatt den Algorithmus zu reproduzieren, den das System verwendet, um nach Zugriffsberechtigungen zu suchen, bitten wir das System, diese Überprüfung mit demselben Algorithmus durchzuführen (der Berechtigungen, ACLs, unveränderliche Flags, schreibgeschützte Dateisysteme berücksichtigt ...). ) Wenn Sie versuchen würden, die Datei zum Schreiben zu öffnen, ist dies die zuverlässigste Lösung.

Um die hier angegebenen Lösungen mit den verschiedenen Kombinationen von Benutzern, Gruppen und Berechtigungen zu testen, können Sie Folgendes tun:

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
            }
          }
        }
      }
    }
  }'

Variieren Sie den Benutzer zwischen 1 und 2 und die Gruppe zwischen 1, 2 und 3 und beschränken Sie sich auf die unteren 9 Bits der Berechtigungen, da bereits 9458694 Dateien erstellt wurden. Das für Verzeichnisse und dann nochmal für Dateien.

Das schafft alle möglichen Kombinationen von u<x>g<y>/<mode1>/u<z>g<w>/<mode2>. Der Benutzer mit Benutzer-ID 1 und Benutzer-ID 1 und Benutzer-ID 2 hätte beispielsweise Schreibzugriff auf, u2g1/010/u2g3/777jedoch nicht u1g2/677/u1g1/777auf.

Alle diese Lösungen versuchen nun, die Pfade der Dateien zu identifizieren, die der Benutzer möglicherweise zum Schreiben öffnet. Dies unterscheidet sich von den Pfaden, unter denen der Benutzer möglicherweise den Inhalt ändern kann. Um diese allgemeinere Frage zu beantworten, gibt es mehrere Dinge zu berücksichtigen:

  1. $ user hat möglicherweise keinen Schreibzugriff auf, /a/b/fileaber wenn er Eigentümer ist file(und Suchzugriff auf /a/bhat und das Dateisystem nicht schreibgeschützt ist und die Datei nicht das unveränderliche Flag hat und Shell-Zugriff auf das System hat), dann könnte er die Berechtigungen des ändern fileund sich selbst Zugriff gewähren.
  2. Dasselbe, wenn er es besitzt, /a/baber keinen Suchzugriff darauf hat.
  3. $ user hat möglicherweise keinen Zugriff auf, /a/b/fileweil er keinen Suchzugriff auf /aoder /a/bhat. Diese Datei verfügt jedoch möglicherweise über einen festen Link /b/c/file. In diesem Fall kann er den Inhalt möglicherweise ändern, /a/b/fileindem er ihn über seinen /b/c/filePfad öffnet .
  4. Gleiches gilt für Bindemounts . Er kann nicht suchen den Zugang haben /a, sondern /a/bkann sein bind montierte in /c, so dass er öffnen konnte filefür das Schreiben über seinen /c/fileanderen Weg.
  5. Er hat möglicherweise keine Schreibrechte für /a/b/file, aber wenn er Schreibrechte hat, /a/bkann er diese entfernen oder umbenennen fileund durch seine eigene Version ersetzen. Er würde den Inhalt der Datei ändern, /a/b/fileselbst wenn dies eine andere Datei wäre.
  6. Das Gleiche gilt , wenn er Schreibzugriff auf bekam ist /a(er umbenennen könnte /a/bzu /a/cerstellen Sie ein neues /a/bVerzeichnis und ein neues filedrin.

Um die Pfade zu finden, die geändert $userwerden könnten. Für Adresse 1 oder 2 können wir uns nicht mehr auf den access(2)Systemaufruf verlassen . Wir könnten unseren find -permAnsatz anpassen , um den Suchzugriff auf Verzeichnisse oder den Schreibzugriff auf Dateien zu übernehmen, sobald Sie der Eigentümer sind:

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

Wir könnten die Adressen 3 und 4 ansprechen, indem wir die Geräte- und Inode-Nummern oder alle Dateien aufzeichnen, für die der Benutzer Schreibrechte besitzt, und alle Dateipfade mit diesen dev + -Inode-Nummern melden. Dieses Mal können wir die zuverlässigeren access(2)Ansätze verwenden:

So etwas wie:

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 und 6 werden auf den ersten Blick durch das tbisschen der Berechtigungen kompliziert . Bei der Anwendung auf Verzeichnisse ist dies das eingeschränkte Löschbit, das verhindert, dass Benutzer (außer dem Eigentümer des Verzeichnisses) die Dateien entfernen oder umbenennen, deren Eigentümer sie nicht sind (obwohl sie Schreibzugriff auf das Verzeichnis haben).

Zum Beispiel, wenn wir zurück zu unserem früheren Beispiel gehen, wenn Sie Schreibzugriff haben /a, dann sollten Sie in der Lage sein , umbenennen /a/bzu /a/c, und dann ein neu - /a/bVerzeichnis und ein neu filedrin. Aber wenn das tBit gesetzt ist /aund Sie es nicht besitzen /a, können Sie es nur tun, wenn Sie es besitzen /a/b. Das gibt:

  • Wenn Sie ein Verzeichnis gemäß Nummer 1 besitzen, können Sie sich selbst Schreibzugriff gewähren, und das t-Bit wird nicht angewendet (und Sie können es trotzdem entfernen), sodass Sie alle Dateien oder Verzeichnisse dort löschen / umbenennen / neu erstellen können Alle Dateipfade, die sich dort befinden, können mit allen Inhalten überschrieben werden.
  • Wenn Sie es nicht besitzen, aber Schreibzugriff haben, dann:
    • Entweder ist das tBit nicht gesetzt, und Sie sind im selben Fall wie oben (alle Dateipfade gehören Ihnen).
    • oder es ist festgelegt und dann können Sie die Dateien nicht ändern, die Sie nicht besitzen oder auf die Sie keinen Schreibzugriff haben. Um die Dateipfade zu ermitteln, die Sie ändern können, müssen Sie also überhaupt keine Schreibberechtigung besitzen.

So können wir alle von 1, 2, 5 und 6 ansprechen mit:

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

Das und die Lösung für 3 und 4 sind unabhängig, Sie können ihre Ausgabe zusammenführen, um eine vollständige Liste zu erhalten:

{
  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{$_}++'

Wie klar sein sollte, wenn Sie bisher alles gelesen haben, befasst sich ein Teil davon zumindest nur mit Berechtigungen und Eigentumsrechten, nicht aber mit den anderen Funktionen, die möglicherweise Schreibzugriff gewähren oder einschränken (schreibgeschütztes FS, ACLs, unveränderliches Flag, andere Sicherheitsfunktionen) ...). Und da wir es in mehreren Schritten verarbeiten, können einige dieser Informationen falsch sein, wenn die Dateien / Verzeichnisse erstellt / gelöscht / umbenannt werden oder ihre Berechtigungen / Eigentümer geändert werden, während das Skript ausgeführt wird, wie auf einem ausgelasteten Dateiserver mit Millionen von Dateien .

Hinweise zur Portabilität

Der gesamte Code ist Standard (POSIX, Unix für tBit), außer:

  • -print0ist eine GNU-Erweiterung, die jetzt auch von einigen anderen Implementierungen unterstützt wird. Mit findImplementierungen , die Unterstützung für sie fehlt, können Sie -exec printf '%s\0' {} +stattdessen und ersetzen -exec sh -c 'exec find "$@" -print0' sh {} +mit -exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +.
  • perlist kein POSIX-spezifizierter Befehl, ist aber weit verbreitet. Sie benötigen perl-5.6.0oder über -Mfiletest=access.
  • zshist kein POSIX-angegebener Befehl. Der zshobige Code sollte mit zsh-3 (1995) und höher funktionieren.
  • sudoist kein POSIX-angegebener Befehl. Der Code sollte mit jeder Version funktionieren, sofern die Systemkonfiguration die Ausführung perlals angegebener Benutzer zulässt .
Stéphane Chazelas
quelle
Was ist ein Suchzugang ? Ich habe in den herkömmlichen Berechtigungen noch nie davon gehört: Lesen, Schreiben, Ausführen.
bela83
2
@ bela83, Ausführungsberechtigung für ein Verzeichnis (Sie führen keine Verzeichnisse aus) übersetzt in eine Suche . Das ist die Möglichkeit, auf Dateien darin zuzugreifen. Sie können den Inhalt eines Verzeichnisses auflisten, wenn Sie über Leseberechtigung verfügen, aber Sie können nichts mit den darin enthaltenen Dateien tun, es sei denn, Sie haben auch die Suchberechtigung ( xBit) für das Verzeichnis. Sie können auch über Suchberechtigungen verfügen, diese jedoch nicht lesen . Dies bedeutet, dass die darin enthaltenen Dateien für Sie verborgen sind. Wenn Sie jedoch ihren Namen kennen, können Sie auf sie zugreifen. Ein typisches Beispiel ist das PHP-Sitzungsdateiverzeichnis (so etwas wie / var / lib / php).
Stéphane Chazelas
2

Sie können Optionen mit dem findBefehl kombinieren , damit die Dateien mit dem angegebenen Modus und Eigentümer ermittelt werden. Zum Beispiel:

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

Der obige Befehl listet alle Einträge auf, die zur Gruppe "Mitarbeiter" oder "Benutzer" gehören und Schreibberechtigung für diese Gruppe haben.

Sie sollten auch nach Einträgen suchen, die Ihrem Benutzer gehören, und nach Dateien, die weltweit beschreibbar sind.

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

Dieser Befehl stimmt jedoch nicht mit Einträgen mit erweiterter ACL überein. So können Sie sudann alle beschreibbaren Einträge herausfinden:

# su - yourusername
$ find / -writable
apaul
quelle
Das würde heißen, dass eine Datei mit r-xrwxrwx yourusername:anygroupoder beschreibbar r-xr-xrwx anyone:staffist.
Stéphane Chazelas
Es würde auch als beschreibbare Dateien melden, auf die in Verzeichnissen yourusernamekein Zugriff besteht.
Stéphane Chazelas
1

Der Ansatz hängt davon ab, was Sie wirklich testen.

  1. Möchten Sie sicherstellen , dass Schreibzugriff möglich ist?
  2. Möchten Sie sicherstellen , dass kein Schreibzugriff besteht?

Dies liegt daran, dass es so viele Möglichkeiten gibt, zu 2) und Stéphanes Antwort diese gut abdeckt (unveränderlich ist eine, an die man sich erinnern muss) Hardware-Level (Floppy-Tabs). Ich vermute, Ihre Tausenden von Dateien befinden sich in unterschiedlichen Verzeichnissen und Sie möchten einen Bericht oder Sie vergleichen eine Master-Liste. (Ein weiterer Missbrauch von Puppet, der nur darauf wartet, geschehen zu können).

Sie möchten wahrscheinlich, dass Stéphanes Perl-Tree-Traversal die Ausgabe bei Bedarf mit einer Liste "verbindet" (su fängt auch die fehlende Ausführung in übergeordneten Verzeichnissen auf?). Wenn Leihmutterschaft ein Leistungsproblem ist, tun Sie dies für eine "große Anzahl" von Benutzern? Oder ist es eine Online-Abfrage? Wenn dies eine ständige Anforderung ist, ist es möglicherweise an der Zeit, ein Produkt von Drittanbietern in Betracht zu ziehen.

mckenzm
quelle
0

Du kannst tun...

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

... für eine Liste aller Dateien, in die der Benutzer nicht schreiben kann , wie in der Form in stderr geschrieben ...

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

...o.ä.

In den Kommentaren unten finden Sie Hinweise zu den Problemen, die bei diesem Ansatz auftreten können, und eine Erläuterung, warum dies möglicherweise funktioniert. Noch vernünftiger sollten Sie jedoch wahrscheinlich nur find reguläre Dateien wie die folgenden verwenden:

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

Kurz gesagt, teewerden Fehler ausgegeben, wenn versucht wird, open()eine Datei mit einem der beiden Flags zu erstellen.

O_WRONLY

Nur zum Schreiben öffnen.

O_RDWR

Zum Lesen und Schreiben öffnen. Das Ergebnis ist undefiniert, wenn dieses Flag auf einen FIFO angewendet wird.

... und Begegnungen ...

[EACCES]

Die Suchberechtigung wird für eine Komponente des Pfadpräfixes verweigert, oder die Datei ist vorhanden, und die von oflag angegebenen Berechtigungen werden verweigert, oder die Datei ist nicht vorhanden, und die Schreibberechtigung für das übergeordnete Verzeichnis der zu erstellenden Datei wird verweigert, oder O_TRUNC lautet angegeben und Schreibberechtigung verweigert.

... wie hier angegeben :

Das tee Dienstprogramm kopiert die Standardeingabe in die Standardausgabe und erstellt eine Kopie in null oder mehr Dateien. Das Dienstprogramm tee puffert keine Ausgabe.

Wenn die -aOption nicht angegeben ist, sollen Ausgabedateien geschrieben werden (siehe Datei lesen, schreiben und erstellen ) ...

... POSIX.1-2008 erfordert Funktionen, die der Verwendung von O_APPEND entsprechen ...

Weil es auf die gleiche Weise zu überprüfen hat, test -wtut ...

-w Pfadname

True, wenn der Pfadname in einen vorhandenen Verzeichniseintrag für eine Datei aufgelöst wird, für die die Berechtigung zum Schreiben in die Datei erteilt wird, wie in Datei lesen, schreiben und erstellen definiert . False, wenn der Pfadname nicht aufgelöst werden kann oder wenn der Pfadname in einen vorhandenen Verzeichniseintrag für eine Datei aufgelöst wird, für die keine Berechtigung zum Schreiben in die Datei erteilt wird.

Beide prüfen auf EACCESS .

mikeserv
quelle
Bei diesem Ansatz ist die Anzahl der gleichzeitig geöffneten Dateien wahrscheinlich begrenzt (es sei denn, die Anzahl der Dateien ist niedrig). Achten Sie auf Nebenwirkungen bei Geräten und Named Pipes. Für Sockets wird eine andere Fehlermeldung angezeigt.
Stéphane Chazelas
@ StéphaneChazelas - Alle tue - Ich denke, es könnte auch wahr sein, dass teees hängen bleibt, wenn nicht einmal pro Lauf explizit unterbrochen wird. Es war das Nächste, woran ich denken konnte [ -w... obwohl - seine Auswirkungen sollten dahingehend ähnlich sein, dass es dem Benutzer garantiert, dass er die Datei anhängen kann. Viel einfacher als jede Option wäre es paxmit -oFormatoptionen und / oder -tzum Abgleichen EACCESS- aber jedes Mal, wenn ich vorschlage pax, scheinen die Leute mit den Schultern zuzucken. Und das Einzige, was paxich gefunden habe und das der Norm entspricht, sind ASTs - in diesem Fall können Sie auch deren verwenden ls.
mikeserv