Как сделать найти все файлы журналов рекурсивно, не указав при этом один конкретный путь отказа в доступе?

Предупреждение относительно '>'

начинающих пользователей Unix, которые только что узнали о перенаправлении ввода-вывода ( и > ) часто пробуют такие вещи, как

commandinput_file > the_same_file

или

command … < file     > the_same_file

или, что почти то же самое,

cat file | command … > the_same_file

( grep , sed , cut , sort и spell являются примерами команд , которые у людей возникает соблазн использовать в подобных конструкциях.) Пользователи с удивлением обнаруживают, что в этих сценариях файл становится пустым.

Нюанс, который, похоже, не упоминается в другом ответе, можно найти в первом предложении раздела Redirection bash (1) ]:

Перед выполнением команды ее ввод и вывод могут быть перенаправлены с использованием специальной записи, интерпретируемой оболочкой.

Первые пять слов должны быть выделены жирным шрифтом, курсивом, подчеркнуты, увеличены, мигают, окрашены в красный цвет и отмечены значком exclamation mark in red triangle , чтобы подчеркнуть тот факт, что оболочка выполняет запрошено перенаправление (я) перед выполнением команды . И помните также

Перенаправление вывода заставляет файл… открываться для записи…. Если файл не существует, он создается; если он существует, он обрезается до нулевого размера.

  1. Итак, в этом примере:

     список сортировки> список 
     

    оболочка открывает файл списка для записи, усекая его (т. Е. Отбрасывая все его содержимое) перед запуском программы sort . Естественно, восстановить данные невозможно.

  2. Можно наивно ожидать, что

     tr "[: upper:]" "[: lower:]"  poem 
     

    может быть лучше. Поскольку оболочка обрабатывает перенаправления слева направо, она открывает стихотворение для чтения (для стандартного ввода tr ) прежде, чем он откроет его для записи (для стандартного вывода). Но это не помогает. Несмотря на то, что эта последовательность операций дает два дескриптора файла, они оба указывают на один и тот же файл. Когда оболочка открывает файл для чтения, содержимое все еще там, , но оно все еще затирается перед выполнением программы.

Итак, что с этим делать?

Решения включают:

  • Проверить, имеет ли программа, которую вы запускаете, собственную внутреннюю возможность указывать, куда идет вывод. Это часто обозначается токеном -o (или - output = ). В частности,

     sort roster -o roster 
     

    примерно эквивалентен

     sort roster> roster 
     

    , за исключением первого случая, программа sort открывает выходной файл. И он достаточно умен, чтобы не открывать выходной файл до тех пор, пока после он не прочитает все входные файлы.

    Аналогичным образом, по крайней мере, в некоторых версиях sed есть параметр -i (редактировать i n место) , который можно использовать для записать вывод обратно во входной файл (опять же, после , все входные данные были прочитаны). Редакторы, такие как ed / ex , emacs , pico и vi / ] vim позволяет пользователю редактировать текстовый файл и сохранять отредактированный текст в исходном файле. Обратите внимание, что ed (по крайней мере) можно использовать не интерактивно.

    • vi имеет связанную функцию. Если вы наберете :%! команда Введите , он запишет содержимое буфера редактирования в команду , прочитает вывод, и вставит его в буфер (заменяющий исходное содержимое).
  • Простой, но эффективный:

     команда  входной_файл >  временный_файл  && mv  временный_файл   входной_файл 

    Недостатком этого является, input_file - это ссылка, она (возможно) будет заменена отдельным файлом. Кроме того, новый файл будет принадлежать вам с защитой по умолчанию. В частности, это несет в себе риск того, что файл станет доступным для чтения всем, даже если исходный input_file не был.

    Варианты:

    • команда input_file > temp_file && cp temp_file input_file && rm temp_file
      что по-прежнему (потенциально) оставит temp_file доступным для чтения всем. Еще лучше:
    • cp input_file temp_file && command temp_file > input_file && rm temp_file
      Они сохраняют статус связи, владельца и режим (защиту) файла, потенциально за счет вдвое большего количества операций ввода-вывода. (Вам может потребоваться использовать такой вариант, как -a или -p на cp , чтобы указать ему сохранять атрибуты.)
    • command input_file > temp_file &&
      cp --attributes-only --preserve = all input_file temp_file &&
      mv temp_file input_file
      (разбит на отдельные строки только для удобства чтения) { {1}} Это сохраняет режим файла (и, если вы root, владелец), , но делает его владельцем вашего (если вы не root), и делает его новым, отдельный файл.
  • В этом блоге (редактирование файлов на месте) предлагается и объясняется

     {rm  input_file  &&  команда …>  входной_файл ; }  input_file 

    Для этого требуется, чтобы команда могла обрабатывать стандартный ввод (но почти все фильтры могут). Сам блог называет это рискованным кладжем и не рекомендует его использовать. И это также создаст новый отдельный файл (ни с чем не связанный), принадлежащий вам и с разрешениями по умолчанию.

  • В пакете moreutils есть команда под названием sponge :

     команда  input_file  | губка  the_same_file 

    См. этот ответ для получения дополнительной информации.

Вот кое-что, что стало для меня полной неожиданностью: синтаксическая ошибка говорит :

[Большинство этих решений] завершится ошибкой в ​​файловой системе, доступной только для чтения, где «только для чтения» означает, что ваш $ HOME будет доступен для записи, {{1 }} но / tmp будет только для чтения (по умолчанию). Например, если у вас Ubuntu и вы загрузились в консоль восстановления, это обычно так. Кроме того, оператор здесь-документа там тоже не будет работать, поскольку он требует / tmp для чтения / напишите , потому что он также запишет туда временный файл.
(см. этот вопрос включает вывод strace 'd)

В этом случае может работать следующее:

  • Только для опытных пользователей : Если ваша команда гарантированно произведет такое же количество выходных данных , что и входные (например, sort или tr без параметра -d или -s ), вы можете попробовать
     команду  input_file  | dd of =  the_same_file  conv = notrunc 
    См. этот ответ и этот ответ для дополнительная информация, включая объяснение вышеизложенного, и альтернативы, которые работают , если ваша команда гарантированно произведет такой же объем выходных данных , как и вход или less (например, grep или cut ). У этих ответов есть то преимущество, что они не требуют свободного места (или требуют очень мало). Ответы выше в форме команда input_file > temp_file &&… четко требовать, чтобы в системе было достаточно свободного места, чтобы она могла одновременно хранить весь входной (старый) файл и выходной (новый) файл; это неочевидно для большинства другие решения (например,, sed -i и sponge ). Исключение: сортировка… | dd… , вероятно, потребуется много свободного места, потому что sort должен прочитать весь свой ввод, прежде чем он сможет записать какой-либо вывод, и, вероятно, буферизует большую часть если не все эти данные во временном файле.
  • Только для опытных пользователей:
     команда  input_file  1   the_same_file 
    может быть эквивалентным ответу dd выше. Синтаксис n file открывает именованный файл в файловом дескрипторе n как для ввода, так и для вывода , без усечения - своего рода комбинация n и n > . Примечание. Некоторые программы (например, cat и grep ) могут отказываться запускаться в этом сценарии , поскольку они могут обнаружить, что входные и выходные данные это один и тот же файл. См. этот ответ для обсуждения вышеизложенного, и сценария, который заставляет этот ответ работать, если ваша команда гарантированно производят тот же объем выходных данных, что и вход или меньше .
    Предупреждение: я не тестировал сценарий Питера, поэтому не ручаюсь за него.

Итак, в чем был вопрос?

Это была популярная тема на U&L; он рассматривается в следующих вопросах:

… и это не считая суперпользователя или Ask Ubuntu. В этот ответ я включил много информации из ответов на вышеупомянутые вопросы , но не всю. (т.е. для получения дополнительной информации прочтите перечисленные выше вопросы и их ответы.)

P.S. У меня нет связи с блогом, который я цитировал выше.

1
21.08.2018, 04:49
3 ответа

Los archivos de registro se almacenan en /var/log, por lo que realmente no es necesario ejecutar finden todo el directorio raíz. Si insiste en hacerlo y desea excluir ese directorio para no recibir errores, su sintaxis debería ser:

find / -wholename /run -prune -o -type f -name '*.log' -print

Ese directorio es el punto de montaje para FUSE y no contiene ningún archivo de registro y /runen sí mismo tiene directorios (al menos en Centos, Fedora y RHEL )dentro de los cuales dará errores de permiso, por lo que el comando anterior excluir el directorio por completo. No tengo instalado Mint, por lo que puede editar el comando para podar más bajo hasta que reciba errores.

Además, una cosa a tener en cuenta es que los archivos de registro no siempre terminan en .logcomo messages, dmesg, crony secure.

1
27.01.2020, 23:44

Solo haz:

 find / -type f -name '*.log' 2>/dev/null

o

find /var -type f -name '*.log'

hasta donde deben estar los registrosvar

0
27.01.2020, 23:44

La expresión correcta para evitar los mensajes de error de "permiso denegado" es:

find <root-path> ! -readable -prune -o <rest of your find arguments>

Aplicar eso a tu respuesta original de la tarea produciría:

find / ! -readable -prune -o -type f -name "*.log"

Eso debería satisfacer su requisito de "ensamblar un comando simple e inteligente". También cumple con el requisito "que no solo filtra a ciegas los mensajes de error" porque solo filtra cosas ilegibles. Su requisito final "pero solo omite aquellos lugares donde realmente no tiene sentido mirar" es otro asunto completamente diferente, y sería una buena pregunta por separado, a saber, '¿Hay alguna forma de que una secuencia de comandos encuentre el directorio raíz de registro del sistema predeterminado?, en el sistema particular en el que se ejecuta el script?'. No tengo conocimiento de una variable de entorno para eso.

0
27.01.2020, 23:44

Теги

Похожие вопросы