Хвост читает целый файл?

Вы думаете что !, * или x имеет особое значение здесь и поэтому волнуются, что могло бы быть некоторое различие среди них.

Факт - то, что эти символы выбраны просто, потому что они выделяются, по крайней мере, к Западным глазам. Эти символы означают отсутствующее значение, или случай исключения или предупреждение. Вы могли поместить boogabooga здесь и имейте точно тот же эффект.

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

Хотя нет никакого различия между этими символами с точки зрения базовой ОС, существуют некоторые конвенции:

  • Когда Linux pwconv(8) программа видит x, это берет это, чтобы означать, что "Я уже переместил этот общедоступный хэш пароля в теневой файл паролей".

    Это не важный случай на практике, потому что дни преобразования в (или, небеса помогают Вам, от), теневые пароли находятся позади нас теперь.

  • Если Вы используете usermod -L или passwd -l заблокировать пользователя, ! имеет особое значение в /etc/shadow потому что это - конвенция для "повреждения этот хеш, таким образом, это больше не соответствует".

    Добавление любого другого символа к сохраненному хешу повредило бы его точно также. Нарушение этой конвенции просто предотвращает usermod -U или passwd -u от разблокирования входа в систему пользователя. Столь же одинаково верный, так как Вы заблокировали его вручную путем добавления поддельного символа, можно разблокировать его вручную путем удаления его.

    Все, что является просто мелочами относительно этого вопроса, как бы то ни было. Существует нет groupmod -L или gpasswd -l, следовательно нет ! конвенция в /etc/group.

    Больше мелочей: если Вы собираетесь заблокировать учетные записи пользователей вручную, необходимо избегать [A-Za-z0-9/\] набор, так как это - допустимые символы для хеша. Это - одна причина usermod использование ! здесь вместо x.

Я не вижу ничто плохого с нормализацией всех Ваш /etc/group поля пароля, если это заставляет Вас чувствовать себя лучше. Таким образом Вы уже говорите, что Вы - счастливое взламывание этих файлов вручную, таким образом, Вы - вероятно, не вид для использования инструментов, которые заботятся о различиях так или иначе. Независимо, изменение не будет иметь эффект на ежедневную работу системы.

114
28.11.2013, 21:52
5 ответов

Нет, tail не читает целый файл, он ищет в конец затем блоки чтения назад, пока ожидаемое количество строк не было достигнуто, затем он отображает строки в надлежащем направлении до конца файла и возможно остается контролирующим файл если -f опция используется.

Отметьте однако это tail не имеет никакого выбора, кроме как считывать целые данные, если обеспечено не seekable вход, например, при чтении из канала.

Так же, при выяснении искать строки, запускающиеся с начала файла, с использованием tail -n +linenumber синтаксис или tail +linenumber нестандартная опция при поддержке, tail очевидно, читает целый файл (если не прервано).

120
27.01.2020, 19:29
  • 1
    Чертовски, слишком быстро :-). Вот соответствующий исходный код. Распечатайте последние строки N_LINES от конца файла FD. Пойдите назад через файл, читая байты 'BUFSIZ' за один раз (кроме, вероятно, первого), пока мы не поразим запуск файла или считаем новые строки ЧИСЛА. –  Patrick 28.11.2013, 11:54
  • 2
    Кроме того, tail +n считает целый файл - сначала, чтобы найти желаемое количество новых строк, затем произвести остальных. –  SF. 28.11.2013, 12:20
  • 3
    @SF. Действительно, ответ обновляется. –  jlliagre 28.11.2013, 12:25
  • 4
    Отметьте это не все tail реализация делает это или делает это правильно. Например, busybox 1.21.1 tail прерван то отношение. Также обратите внимание, что поведение варьируется когда tailлуг stdin и где stdin является регулярным файлом и исходным положением в файле, не вначале когда tail вызывается (как в { cat > /dev/null; tail; } < file) копия на записи –  Stéphane Chazelas 28.11.2013, 12:59
  • 5
    @StephaneChazelas *отклоняет - мир странных пограничных случаев, становящихся нормальным. (Хотя seekable по сравнению с non-seekable исходные данные определенно актуальный вопрос.) А-ч –  a CVn 28.11.2013, 13:49

Вы, возможно, видели как tail работы самостоятельно. Поскольку Вы можете для одного из моих файлов read сделан три раза, и всего примерно 10K байты читаются:

strace 2>&1  tail ./huge-file >/dev/null  | grep -e "read" -e "lseek" -e "open" -e "close"
open("./huge-file", O_RDONLY)           = 3
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_END)                   = 80552644
lseek(3, 80551936, SEEK_SET)            = 80551936
read(3, ""..., 708) = 708
lseek(3, 80543744, SEEK_SET)            = 80543744
read(3, ""..., 8192) = 8192
read(3, ""..., 708) = 708
close(3)                                = 0
70
27.01.2020, 19:29
  • 1
    , который я не вижу, как это отвечает на вопрос. Можно ли объяснить, что продолжается здесь? –  Iain Samuel McLean Elder 29.11.2013, 17:27
  • 2
    strace шоу, что системные вызовы tail сделайте когда выполнения. Некоторый introdaction о системных вызовах можно прочитать здесь en.wikipedia.org/wiki/System_call. Кратко - открытый - открывает файл и возвращает дескриптор (3 в этом примере), lseek положения, куда Вы собираетесь читать и read просто чтения и поскольку Вы видите его, возвращаются, сколько байта читаются, –  Sergey Kurenkov 29.11.2013, 17:34
  • 3
    Так анализ системных вызовов, которые можно иногда понимать, как работает программа. –  Sergey Kurenkov 29.11.2013, 17:41

Так как файл мог бы быть рассеян на диске I, предполагают, что он имеет к [читает файл последовательно], но я не понимаю такие внутренности хорошо.

Поскольку Вы теперь знаете, tail просто ищет в конец файла (с системным вызовом lseek), и работает назад. Но в комментарии, заключенном в кавычки выше, Вы задаетесь вопросом, "как хвост знает где на диске находить конец файла?"

Ответ прост: Хвост не знает. Процессы уровня пользователя рассматривают файлы как непрерывные потоки, таким образом, все tail может знать смещение от запуска файла. Но в файловой системе, "inode" файла (запись каталога) связан со списком чисел, обозначающих физическое местоположение блоков данных файла. То, когда Вы читаете из файла, ядро / драйвер устройства выясняет, в какой части Вы нуждаетесь, разрабатывает ее местоположение на диске и выбирает ее для Вас.

Это - вид вещи, для которой у нас есть операционные системы: таким образом, Вы не должны волноваться о том, где блоки Вашего файла рассеиваются.

26
27.01.2020, 19:29

Если head или tail кажется, что читается весь файл, то вероятная причина в том, что файл содержит мало символов новой строки. Я споткнулся на этом несколько месяцев назад с очень большим (гигабайты) блобом JSON, который был сериализован без пробельных символов, даже в строках.

Если у вас есть GNU head/tail, вы можете использовать -c N для печати первых/последних N байт вместо строк, но, к сожалению, это не является функцией POSIX.

2
20.08.2021, 13:01

Как видно из исходного кода , строка 525,вы можете увидеть комментарии к реализации.

 /* Print the last N_LINES lines from the end of file FD.
   Go backward through the file, reading 'BUFSIZ' bytes at a time (except
   probably the first), until we hit the start of the file or have
   read NUMBER newlines.
   START_POS is the starting position of the read pointer for the file
   associated with FD (may be nonzero).
   END_POS is the file offset of EOF (one larger than offset of last byte).
   Return true if successful.  */
1
20.08.2021, 13:01

Теги

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