Чому вимкнення моєї машини після поганого `rm` зберегло мої файли?


31

Класична ситуація: я побіг погано rmі відразу після цього зрозумів, що видалив неправильні файли. (Нічого критичного, і у мене були терпимі останні резервні копії, але все ще дратує.)

Знаючи, що подальша активність диска була моїм ворогом, якщо я хотів відновити файли за допомогою extundeleteтаких інструментів, я негайно вимкнув машину фізично (тобто за допомогою кнопки живлення, а не з haltбудь-якою командою). Цей ноутбук не мав жодних важливих завдань і нічого відкритого, тому це було прийнятною операцією. (До речі, з того часу я дізнався, що перше, що потрібно зробити в такій ситуації, - це спочатку оцінити, чи відсутні файли все-таки можуть бути відкриті процесом https://unix.stackexchange.com/a/101247 - якщо вони є, вам слід відновити їх таким чином, а не вимикати живлення машини.)

І все-таки, коли машина вимкнулася, я деякий час подумав і вирішив, що файли не варті того часу, щоб вкласти кошти живої системи для належної криміналістики. Тому я підключив машину назад. І тоді я виявив, що мої файли все ще сидять на диску: rmвони не були передані на диск до того, як я вимкнувся. Я трохи потанцював і подякував богу сисадмінів за його несподіване прощення.

Моє запитання тепер полягає в тому, щоб зрозуміти, як це стало можливим, і яка типова затримка перед тим, як rmнасправді передається на диск. Я знаю, що IO диска не змивається відразу, але він деякий час залишається в пам'яті, але я подумав, що журнал дисків швидко переконається, що очікувані операції не втратяться повністю. https://unix.stackexchange.com/a/78766, схоже, натякає на окремий механізм для промивання брудних сторінок та для очищення журнальних операцій, але не дає достатньо детальних відомостей про те, як журнал буде задіяний для rm, та очікувану затримку до операції промиті.

Ще деякі деталі: дані знаходилися в розділі ext4 всередині LUKS-тому, і під час завантаження машини резервного копіювання я побачив наступне в syslog:

Sep 24 10:24:58 gamma kernel: [   11.457007] EXT4-fs (dm-0): 1 orphan inode deleted
Sep 24 10:24:58 gamma kernel: [   11.458393] EXT4-fs (dm-0): recovery complete
Sep 24 10:24:58 gamma kernel: [   11.482475] EXT4-fs (dm-0): mounted filesystem with ordered data mode. Opts: (null)

але я не впевнений, що це пов'язано з rm.

Інше питання полягає в тому, чи є спосіб сказати ядру не виконувати жодних операцій, що очікують на диску (а, скажімо, скинути їх кудись), а не живити машину. (Звичайно, це не небезпечно виконувати очікувані операції, але це буде те, що все одно відбудеться при вимкненні машини, і це може врятувати вас у деяких випадках.) Звичайно, це було б "чистіше", а також цікаво наприклад, віддалені сервери, де фізичне вимкнення живлення не є простим варіантом.

Відповіді:


22

Це здається, що ви гідно зрозуміли те, що сталося.

Так, оскільки ви відключили систему до того, як зміни відбулися на диску, вони були там, коли ви завантажували резервну копію.

Система кешує всі записи перед тим, як видалити їх на диск. Є кілька варіантів, які керують такою поведінкою, і всі вони розташовані в /proc/sys/vm/dirty_* [ kernel doc ] . Якщо флеш явно не виконується програмою через fsync() [ man 2 fsync ] , дані фіксуються , коли вони досить старі, або кеш запису заповнений.
Визначення "даних", як було використано вище, включає внесення змін до запису каталогу для видалення файлу.

Що стосується журналу, то це одна з поширених помилок того, для чого журнал. Метою журналу є не забезпечити повторне внесення змін або не втратити дані. Мета журналу - запобігти пошкодженню самої файлової системи, а не файлів у ній. Журнал просто містить інформацію про внесені зміни, а не (як правило) повні дані самих змін. Точні деталі залежать від файлової системи та режиму журналу. Щодо ext3 / 4, див. dataОпцію кріплення в man 8 mount.


Щоб відповісти на ваше додаткове запитання, чи є спосіб запобігти відкладеному запису без перезавантаження:

З швидкого читання вихідного коду ядра, схоже, що ви можете скористатися магічною uкомандою sysrq ([ wikipedia ], [ kernel doc ]), щоб зробити екстрену операцію повторного перегляду читання лише для читання. Здається, це негайно перезавантажить усі томи, які читаються лише без операції синхронізації.

Для цього просто натисніть Alt+ SysRq+ u.


1
Дякую за цю відповідь! Я все ще трохи розгублений щодо журналу: чи слід вважати це як щось, що втягується лише тоді, коли зміни перекидаються на диск, так що кешування записів - єдиний відповідний механізм для оцінки часу грації перед тим, як rmпочинає писатися? Інакше кажучи, речі вносяться до журналу лише тоді, коли написання збирається виконати? Або картина складніша за це? Що стосується alt-sysrq-u, то це досить акуратна ідея. Чи маєте ви посилання на претензію "Здається"? (Схоже, це не випливає із посилань, які ви дали.) Дякую! :)
a3nm

Також магічний sysrq також має обмеження, що ви все одно не можете це зробити на віддаленій машині.
a3nm

3
@ a3nm Ви можете використовувати sysrq на віддаленій машині. echo u > /proc/sysrq-trigger(можливо, вам потрібно буде активувати її спочатку).
Пауло Альмейда

Журнал не стосується вмісту файлу (за замовчуванням він може бути змінений повністю з журналом), лише з метаданими файлової системи, але в цьому випадку він міг видалити файл , оскільки ми маємо справу з видаленням запису в каталозі. Таким чином, журнал повинен переконатися, що або файл існує (з його попереднім вмістом, якщо припустити, що інших змін не було), або він не має.
Ángel

@ a3nm Що стосується Вашого коментаря до журналу. Кеш запису знаходиться між журналом і диском. Коли ви пишете у файлову систему, журнал оновлюється, потім файлова система, але жодна з них не присвячена диску.
Патрік

2

З: https://www.kernel.org/doc/Documentation/filesystems/ext4.txt

commit = nrsec (*) Ext4 можна сказати, щоб синхронізувати всі свої дані та метадані кожні 'nrsec' секунди. Значення за замовчуванням - 5 секунд. Це означає, що якщо ви втратите свою силу, ви втратите стільки ж, скільки останні 5 секунд роботи (ваша файлова система не буде пошкоджена, хоча завдяки журналу). Це значення за замовчуванням (або будь-яке низьке значення) пошкодить продуктивність, але це добре для безпеки даних. Якщо встановити 0, матиме такий самий ефект, як і за умовчанням (5 секунд). Встановлення дуже великих значень покращить продуктивність.

Також дивіться тут, як їх очистити : Як ви спорожнюєте буфери та кеш в системі Linux?

Цитується за вищенаведеним посиланням:

ПРИМІТКА: очищення пам’яті від непотрібних речей (Kernerl 2.6.16 або новіших версій). Завжди переконайтеся, що запускайте синхронізацію спочатку, щоб видалити корисні речі на диск !!!

To free pagecache:

$ echo 1 > /proc/sys/vm/drop_caches

To free dentries and inodes:

$ echo 2 > /proc/sys/vm/drop_caches

To free pagecache, dentries and inodes:

$ echo 3 > /proc/sys/vm/drop_caches

Дякую за цю відповідь! Однак я цього не розумію: що стосується цієї "синхронізації", про яку згадується commit=nrsec, чи це щось, що відбудеться після того, як ядро ​​вирішить перевести зміни з пам'яті на диск? Або встановлення commit=1гарантує, що всі зміни будуть спущені через 1 секунду незалежно від dirty_expire_centisecsта dirty_writeback_centisecsналаштувань?
a3nm

Ядро буде видаляти (синхронізувати) будь-який кеш / буфер на диску кожні 1 секунди commit=1. Наскільки я розумію, це syncзмушує все статися незалежно від налаштувань віртуальної пам'яті, хоча це може статися і раніше.
Девід

Також з міркувань продуктивності (і тривалості зберігання) встановлення встановлення на значення нижче за замовчуванням не рекомендується.
Девід
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.