Tak trochu o súboroch
Ešte predtým, ako prejdeme k odpovedi na pôvodnú otázku, si o súboroch niečo málo povieme. V princípe potrebujeme vedieť, že každý súbor je definovaný:
- svojim obsahom, a
- svojimi vlastnosťami.
Ak je súbor nositeľom údajov istého druhu, tak tieto údaje tvoria práve obsah súboru. Ak sa jedná o textový súbor, bude to text, ktorý bude možné zobraziť alebo upraviť v ľubovoľnom textovom editore. Ak súbor reprezentuje fotografiu, bude sa jednať o binárne údaje, ktoré je možné zobraziť v prehliadači obrázkov.
Vlastnosti zasa nesú doplnkové údaje o celom súbore. Môžeme ich priamo nazvať metaúdajmi - teda údajmi (vlastnosťami) o údajoch (obsahu súboru). Medzi tieto údaje patria informácie ako názov súboru, veľkosť súboru, vlastník súboru, prístupové práva k súboru a podobne.
Pre zistenie odpovede na pôvodnú otázku sa pozrieme bližšie práve na vlastnosti súboru. Tie sa nachádzajú v štruktúre, ktorá sa volá inode a môžeme si ich zobraziť pomocou príkazu stat
.
Príkaz stat
Ak sa pozrieme do manuálovej stránky tohto príkazu, dozvieme sa, že príkaz zobrazuje stav súboru (z orig. file status). Vyskúšajme si teda, ako bude vyzerať jeho výstup:
$ touch subor.txt $ stat subor.txt File: 'subor.txt' Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: fd02h/64770d Inode: 1588088 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 1000/ mirek) Gid: ( 1000/ mirek) Context: unconfined_u:object_r:user_home_t:s0 Access: 2016-08-31 19:26:30.021906753 +0200 Modify: 2016-08-31 19:26:30.021906753 +0200 Change: 2016-08-31 19:26:30.021906753 +0200 Birth: -
Okrem už spomenutých vlastností súboru sa tu nachádzajú aj tri časy nazvané ako Access (Time), Modify (Time) a Change (Time). Ak teda hľadáme odpoveď na otázku, kedy bol súbor vytvorený, bude sa nachádzať zrejme tu.
Modification Time alebo čas poslednej zmeny obsahu súboru
Modification time (skrátene mtime) je čas poslednej zmeny obsahu súboru. Kedykoľvek súbor otvoríte a vykonáte v ňom akúkoľvek zmenu alebo ho proste len uložíte, dôjde k aktualizácii tohto času. K aktualizácii tohto času však nedôjde vtedy, ak zmeníte niektorú z vlastností súboru.
Access Time alebo čas posledného prístupu k súboru
Access time (skrátene atime) je čas posledného prístupu k súboru. Tento čas sa aktualizuje zakaždým, keď dôjde k otvoreniu súboru. K aktulizácii však dôjde rovnako aj v prípade, ak so súborom pracujete s nástrojmi ako napr. cat
, sed
, tr
, grep
a podobne.
Change Time alebo čas poslednej zmeny vlastností súboru
Change time (skrátene ctime) predstavuje čas poslednej zmeny niektorej z vlastností súboru, ktoré sú uložené v inode. Napr. ak zmeníte vlastníka súboru, prístupové práva súboru, ale rovnako dôjde k aktualizácii aj vtedy, ak sa zmení veľkosť súboru.
Niekoľko príkladov
Na niekoľkých príkladoch si teraz ukážeme, ako je to s jednotlivými časmi súboru v praxi. Začneme tým, že vytvoríme nový (prázdny) súbor (opäť) pomocou príkazu touch
:
$ touch experiment.txt $ stat experiment.txt File: 'experiment.txt' Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: 29h/41d Inode: 1500352 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 1000/ mirek) Gid: ( 1000/ mirek) Context: unconfined_u:object_r:user_tmp_t:s0 Access: 2016-09-01 17:09:03.212380264 +0200 Modify: 2016-09-01 17:09:03.212380264 +0200 Change: 2016-09-01 17:09:03.212380264 +0200 Birth: -
Priamo po vytvorení sú samozrejme všetky časy nastavené na rovnakú hodnotu - v tomto prípade je to dátum a čas 2016-09-01 17:09:03.212380264 +0200.
Teraz sa však pozrime na to, ako sa zmení hodnota atime, ak si necháme zobraziť obsah súboru:
$ cat experiment.txt $ stat experiment.txt File: 'experiment.txt' Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: 29h/41d Inode: 1500352 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 1000/ mirek) Gid: ( 1000/ mirek) Context: unconfined_u:object_r:user_tmp_t:s0 Access: 2016-09-01 17:11:46.342097172 +0200 Modify: 2016-09-01 17:09:03.212380264 +0200 Change: 2016-09-01 17:09:03.212380264 +0200 Birth: -
Ako je vidieť z výpisu príkazu stat
, došlo k zmene len hodnoty času posledného prístupu k súboru, pretože nedošlo ani k zmene jeho obsahu a ani k zmene jeho vlastností.
Skúsme teraz opäť zobraziť obsah súboru pomocou rovnakého príkazu, aby sme si overili správanie, že opäť dôjde k aktualizácii hodnoty času posledného prístupu k súboru:
$ cat experiment.txt $ stat experiment.txt --format="atime: %x mtime: %y ctime: %z" atime: 2016-09-01 17:11:46.342097172 +0200 mtime: 2016-09-01 17:09:03.212380264 +0200 ctime: 2016-09-01 17:09:03.212380264 +0200
Tentokrát som použil formátovaný výpis a nechal som vypísať len uvedené časy. Ak však porovnáte predchádzajúci výstup s aktuálnym, všimnete si, že ku žiadnej aktualizácii času poslednej zmeny nedošlo aj napriek tomu, že by k jeho aktualizácii dôjsť malo. Kde je teda chyba?
V tomto prípade sa nejedná o žiadnu chybu, ako by sa na prvý pohľad mohlo zdať. Aby sme však porozumeli tomuto správaniu, musíme si uvedomiť jednu veľmi dôležitú vec, ktorá sa deje na pozadí súborového systému. Ak dochádza k zápisu súboru, jedná sa o aktualizáciu hodnôt ctime a mtime. Ak však dochádza k čítaniu súboru, jedná sa o aktualizáciu hodnoty atime. Dôsledkom tohto správania v POSIX-ových systémoch však súčasne s čítaním údajov zo súboru (napr. pomocou príkazu cat
) dochádza aj k zápisu údajov (aktualizácia času poslednej zmeny - atime). Toto správanie bolo dlhodobo kritizované a vývojár jadra Ingo Molnár dokonca o hodnote atime povedal, že sa jedná "pravdepodobne o najhlúpejší nápad v rámci dizajnu Unix-u všetkých čias" dodávajúc: "Len si to predstavte: Pri každom jednom čítaní súboru z disku urobme... zápis na disk! A pre každý súbor, ktorý sa už nachádza v cache, a ktorý budeme z chace čítať, urobme... zápis na disk!". Aktualizácia hodnoty atime predstavuje jeden z najväčších nedostatkov výkonu IO, ktoré Linux v súčasnosti má.
Toto správanie je však možné zmeniť, čím ale dôjde k porušeniu POSIX-u a niektoré aplikácie kvôli tomu nemusia pracovať správne. Jadro ponúka niekoľko možností, ktorými je možné ovplyvniť toto správanie a je možné ho nastaviť pri pripájaní súborového systému alebo priamo v súbore /etc/fstab
.
Teraz sa však pozrime na to, ako môžeme ovplyvniť hodnotu ctime a teda čas, kedy došlo k aktualizácii niektorej z vlastností nachádzajúcich sa v metaúdajoch súboru (v inode). Ilustrujeme si teda aktualizáciu tejto hodnoty pomocou zmeny prístupového práva k súboru:
$ chmod o+w experiment.txt $ stat experiment.txt --format="atime: %x mtime: %y ctime: %z" atime: 2016-09-01 17:11:46.342097172 +0200 mtime: 2016-09-01 17:09:03.212380264 +0200 ctime: 2016-09-01 17:44:23.739689080 +0200
Ak teda porovnáme predposledný výpis príkazu stat
s posledným, došlo k zmene len hodnoty ctime.
Nakoniec sa pozrime na to, ako dôjde k aktualizácii hodnoty mtime, ku ktorej dôjde v prípade zmeny obsahu súboru:
$ echo "This is a test" > experiment.txt $ stat experiment.txt File: 'experiment.txt' Size: 15 Blocks: 8 IO Block: 4096 regular file Device: 29h/41d Inode: 1500352 Links: 1 Access: (0666/-rw-rw-rw-) Uid: ( 1000/ mirek) Gid: ( 1000/ mirek) Context: unconfined_u:object_r:user_tmp_t:s0 Access: 2016-09-01 17:11:46.342097172 +0200 Modify: 2016-09-01 17:47:26.985383553 +0200 Change: 2016-09-01 17:47:26.985383553 +0200 Birth: -
Pri porovnaní týchto dvoch posledných výstupov príkazu stat
si môžeme všimnúť, že nedošlo len k aktualizácii času hodnoty mtime, ale rovnako aj k aktualizácii hodnoty ctime. Ak si však uvedomíme, že hodnota ctime sa aktualizuje vtedy, ak dôjde k aktualizácii niektorej z vlastností súboru v inode, tak nemôžeme byť prekvapení - tým, že sme do súboru zapísali údaje, došlo k aktualizácii jeho dĺžky. Nutne sa teda aktualizovala aj hodnota ctime. Prakticky to znamená, že ak vykonáte akúkoľvek operáciu zápisu alebo prepisu údajov v súbore, dôjde okrem aktualizácie hodnoty mtime aj k aktualizácii hodnoty ctime.
Príkaz ls
Ako je to teda s príkazom ls
? Ktorý čas vlastne pri voľbe dlhého výpisu (-l
) zobrazí?
Ak sa pozrieme do manuálovej stránky príkazu ls
podrobnejšie, nájdeme v nej prepínač --time
, pomocou ktorého môžeme určiť, aký čas sa bude v dlhom výstupe príkazu zobrazovať. Táto voľba má dve možnosti:
-
atime
(skrátene prepínač-u
) pre zobrazovanie času posledného prístupu, alebo -
ctime
(skrátene prepínač-c
) pre zobrazovanie času poslednej zmeny vlastností súboru
Pokiaľ nevyužijeme ani jednu možnosť, predvolene sa zobrazuje hodnota mtime a teda čas poslednej zmeny obsahu súboru.
Creation Time alebo dátum vytvorenia súboru?
Ak sa teda vrátime k pôvodnej otázke, jedná sa o chyták. Dalo by sa síce polemizovať, že za istých okolností je možné považovať hodnotu mtime za čas vytvorenia súboru, ale to rozhodne nebude platiť vždy.
Ak sa však pozrieme do histórie, hodnota ctime naozaj reprezentovala čas a dátum vytvorenia súboru (z angl. Creation Time). Postupne sa však z tejto hodnoty stala hodnoty času poslednej zmeny vlastností súboru tak, ako ho poznáme dnes.
Použité zdroje
- manuálová stránka príkazu
ls
- manuálová stránka príkazu
stat
-
Wikipédia: príkaz
ls
- Difference between mtime, ctime and atime
- Quora: What is the difference between mtime, atime and ctime?
- nixCraft: Understanding UNIX / Linux filesystem Inodes
- Wikipédia: Inode
-
Wikipédia: príkaz
stat
- SuperUser: Why is cat not changing the access time?
Jj, pamätám si ako pred pár rokmi bola veľká diskusia medzi jadrákmi, že v Linuxe neexistuje možnosť ako zistiť kedy súbor vznikol.
No moderné FS mimo štandard už tento údaj poskytujú.
hmm... diky za tip - rad sa na to kuknem, ako to vyzera v jednotlivych systemoch.
Hoď do vyhľadávača "Linux xstat".
Win na uchovávanie času vytvorenia používa Hack nazvaný "File System Tunneling" (z diskusie o xstat).
Linus ako obyčajne v diskusií zabodoval, či je potrebné vôbec takú vec riešiť, keď sa nevedia dohodnúť ani na jej názve.