Вы обычно, cat /dev/null > [something]
когда вы хотите стереть содержимое файла, при этом гарантируя, что нет абсолютно никакого риска прерывания к фактическому состоянию файла. Содержимое файла будет явно удалено, cat /dev/null
но сам файл - так как он существует и известен файловой системе, в которой он находится - все равно будет там с тем же номером инода, владельцем и разрешениями.
В случае файла журнала может случиться так, что сам файл журнала помечается как «используемый» другим процессом. Это, например rm /var/log/messages && touch /var/log/messages
, может нарушить работу других процессов и может привести к тому, что запущенные процессы будут подавлены. То есть процесс, который каким-то образом привязан к определенному номеру инода, связанному с файлом, /var/log/messages
может внезапно запаниковать и сказать: «Эй! Что случилось /var/log/messages
! », Даже если файл все еще там. Не говоря уже о потенциальных проблемах с владельцем и разрешениями, которые восстанавливаются неправильно.
Из-за этой неопределенности в использовании / состоянии файла cat /dev/null > [something]
предпочтение отдается системным администраторам, которые хотят очистить журнал, но не хотят потенциально вмешиваться в работу уже существующих процессов.
Также в контексте страницы, на которую вы ссылаетесь, автор заявляет следующее:
Здесь нет ничего необычного, только набор команд, которые так же легко можно было бы вызывать по одной из командной строки на консоли или в окне терминала. Преимущества размещения команд в сценарии выходят далеко за пределы необходимости повторного их ввода.
Таким образом, «ничего необычного», о котором упоминает автор, касается всей концепции того, что представляет собой этот конкретный сценарий bash: это просто набор простых команд, которые можно так же легко запускать из командной строки, но помещать в текстовый файл для избегайте перепечатывать их снова и снова.
truncate -s 0
сделал бы то же самое и был бы менее идиоматичным. Тем не менее, программисты оболочки - консервативная группа, и можно встретить системы, достаточно старые или странные, чтобы не иметь этой команды.cat /dev/null > /foo/bar
файл;echo "" > /foo/bar
обрезает его, а затем пишет один символ новой строки.Вы сделаете это, чтобы обрезать содержимое файла, не затрагивая индекс. Все программы, в которых этот файл открыт для чтения или записи, не будут затронуты, за исключением того, что размер файла будет сброшен на ноль.
Часто встречается фиктивная альтернатива - удаление файла, а затем его создание:
или подобное:
Проблема заключается в том, что эти методы не предотвращают запись старого файла какими-либо процессами, у которых удаленный файл открыт во время удаления. Причина заключается в том, что в файловых системах Unix при удалении файла вы только отсоединяете его имя (путь) от его содержимого (inode). Индод сохраняется, пока существуют процессы, в которых он открыт для чтения или записи.
Это приводит к нескольким негативным последствиям: журналы, записанные после удаления файла, теряются, поскольку не существует простого / портативного способа открыть удаленный файл. Пока процесс выполняет запись в удаленный файл, его содержимое все еще использует пространство в файловой системе. Это означает, что если вы удалите / создадите файл, потому что он заполнил ваш диск, диск останется заполненным. Один из способов решения этой последней проблемы - перезапустить процессы регистратора, но вы можете этого не делать, поскольку критически важные службы и промежуточные журналы будут окончательно потеряны. Существуют также побочные эффекты, связанные с тем, что создаваемый файл может не иметь таких же прав доступа, владельца и группы, как у исходного. Это, например, может помешать анализатору журналов читать вновь созданный файл, или, что еще хуже, запретить процессу журналирования записывать собственные журналы.
Первый способ,
cat /dev/null > file
достичь цели должным образом, однако, несмотря на цепкую городскую легенду, егоcat /dev/null
часть абсолютно бесполезна. Он открывает псевдо-файл, который пуст по своей структуре, он не может прочитать что-либо из него и, наконец, просто выходит. Использование этой команды - это пустая трата нажатий клавиш, байтов, системных вызовов и циклов ЦП, и ее можно заменить без каких-либо функциональных изменений, несомненно, более быстрой командой no-op:
или даже, с большинством оболочек, вообще без команды.Позвольте мне попробовать метафору, чтобы объяснить, насколько бесполезно
cat /dev/null
. Допустим, ваша цель - опустошить стакан.Сначала вы удалите из него любую жидкость. Этого достаточно и это именно то, что (
> file
) делает, учитывая, что перенаправления факта всегда обрабатываются первыми.Затем вы выбираете пустую бутылку (
/dev/null
) и выливаете ее в пустой стакан (cat
). Это бессмысленный шаг ...Если вы прочитаете связанный документ до конца, вы можете заметить комментарии в этой строке из расширенной версии скрипта:
Они действительно есть; слишком плохо
cat /dev/null
было сохранено в коде.Это означает, что следующий код будет работать со всеми распространенными оболочками (
csh
иsh
семействами):и это будет работать со всеми оболочками , используя синтаксис Bourne, как
ash
,bash
,ksh
,zsh
и любит:Однако обратите внимание, что с древними оболочками Борна до POSIX любая из этих команд, в том числе
cat /dev/null
не будет обрезать файл, если он будет записан потом еще работающим сценарием оболочки, добавляющим к нему. Вместо файла нулевого байта это будет разреженный файл с неизменным размером. То же самое произойдет, если файл будет записан процессом, ищущим позицию, которую он считает текущей, перед записью.Помните также, что некоторые альтернативные решения, часто предлагаемые для усечения файла, имеют недостатки.
Оба из следующих просто не делают работу. Полученный файл не пустой, но содержит пустую строку. Это сломало бы лог-файлы,
wtmp
которые хранят записи фиксированной ширины.Следующий, основанный на
sh
опции BSD, не переносимый, POSIX не указывает никаких разрешенных опций для echo, поэтому вы можете получить файл, содержащий строку с "-n
":Это тоже не переносимо с помощью
sh
escape-последовательности System V. Некоторые оболочки создают файл, содержащий строку с "\c
":Тот использует команду, предназначенную для работы. Проблема в том, что
truncate
она не переносима, поскольку эта команда, не указанная в POSIX, может отсутствовать в системе Unix / Linux.Наконец, вот пара альтернатив, которые являются портативными и будут правильно выполнять свою работу:
Явная печать пустой строки в файл:
Используя
true
команду, которая строго эквивалентна команде no-op,:
хотя и более читабельной:источник
csh
реализаций, хотя это не обязательно задокументировано. Соcsh
страницы руководства Solaris: Null command. This command is interpreted, but performs no action.
. Я не нашел упоминания об этом ни наtcsh
странице руководства, ни в оригинальной BSDcsh
, но этот синтаксис всегда мог работать.cat /dev/null
- сделать ваши намерения явными./dev/null
эффективного способа ввода нулевых байтов, во всяком случае, более надежного, чем использование:
или ничего. На этой самой странице ответ Сайруса, который был лаконичным, но прямо к делу, имел нулевые голоса, в то время как тот, кто оспаривал этот факт,cat /dev/null
был Джейком Гулдом, но не участвовал (см. Наши комментарии) и уже набрал по меньшей мере четыре голоса.>
или:
непонятный. Я согласен, что это позор, что мифы были распространены из-за его использования.printf "" > file
что является как переносным (POSIX), так и легким, что часто реализуется как встроенная оболочка.Это громоздкий способ довести файл до нулевого размера.
источник
csh
.: > messages
тоже работает.:
илиtrue
более очевидный выбор для команд, которые ничего не выводят и возвращают true.Обрезать открытый файл. Это эквивалентно и более понятно:
(Добавлен -n, чтобы избежать новой строки)
источник
wtmp
случае. Смотрите мой обновленный ответ.bash
,-n
в противном случае не гарантируется работа во всех оболочках Борна.