bash while цикл по файлу не заканчивается при удалении файла
У меня есть цикл while в скрипте bash:
Пример:
while read LINE
do
echo $LINE >> $log_file
done < ./sample_file
У меня вопрос, почему, когда я удаляю файл sample_file во время выполнения скрипта, цикл не заканчивается, и я вижу, что файл log_file обновляется? Как цикл продолжается, пока нет ввода?
3 ответа
Смотрите "Почему файл доступен после удаления в unix?" для превосходного объяснения того, что вы наблюдаете здесь.
Короче...
В основе rm и любой другой команды, которая может появиться для удаления файла, лежит системный вызов unlink. И это называется unlink, not remove или deletefile или чем-то подобным, потому что он не удаляет файл. Он удаляет ссылку (также известную как запись каталога), которая представляет собой связь между файлом и именем в каталоге.
Вы можете использовать функцию truncate
уничтожить фактическое содержимое (или shred
если вам нужно быть более защищенным), что немедленно остановит выполнение вашего примера цикла.
В Unix файл не удаляется, пока не будет удалена последняя запись в каталоге (например, с rm
) и последний дескриптор открытого файла для него закрыт. Смотрите этот вопрос (особенно ответ MarkR) для получения дополнительной информации. В случае вашего скрипта файл открывается как stdin для while read
цикл, и пока этот цикл не выйдет (или не закроет свой стандартный ввод), rm
если файл не будет фактически удален с диска.
Вы можете увидеть этот эффект довольно легко, если хотите. Откройте три окна терминала. Во первых запустите команду cat >/tmp/deleteme
, Во втором беги tail -f /tmp/deleteme
, В третьей, после запуска двух других команд, запустите rm /tmp/deleteme
, На данный момент файл был удален, но оба cat
а также tail
процессы имеют открытые файловые дескрипторы для этого, таким образом это фактически не было удалено. Вы можете доказать это, набрав в первом окне терминала (работает cat
), и каждый раз, когда ваш удар возвращается, tail
увидит новую строку, добавленную в файл, и отобразит ее во втором окне.
Файл на самом деле не будет удален, пока вы не завершите эти две команды (Control-D завершится cat
, но вам нужен Control-C, чтобы убить tail
).
Моментная оболочка выполняет цикл while, sample_file
содержимое было прочитано, и не имеет значения, существует ли файл после этого момента.
Тестовый скрипт:
$ cat test.sh
#!/bin/bash
while read line
do
echo $line
sleep 1
done < data_file
Тестовый файл:
$ seq 1 10 > data_file
Теперь в одном терминале вы запускаете скрипт, в другом терминале вы идете и удаляете файл data_file
вы все равно увидите цифры от 1 до 10, напечатанные сценарием.