Fil
et navngivet sæt data, der gemmes som én enhed
Hvad det er
En fil er det, et program beder styresystemet om, når det vil have de samme bytes tilbage i morgen: det åbner filen ved navn, læser eller skriver, lukker den og stoler på, at det næste program, der åbner det navn, ser det, der blev efterladt. Dokumenter, billeder, programmer, indstillinger og logge er alle filer, og på Unix-lignende systemer er flere ting, der slet ikke er gemt nogen steder, det også.
POSIX, standarden bag Linux, macOS og de andre Unix-lignende systemer, definerer en fil som et objekt, der kan skrives til, læses fra eller begge dele, med egenskaber, som blandt andet omfatter adgangsrettigheder og type. Derefter opregner den typerne: almindelige filer, mapper, symbolske links, FIFO’er, sockets samt tegn- og blokspecialfiler, som står for enheder som en terminal eller en disk. Når folk siger fil, mener de næsten altid den første slags, som standarden beskriver som en række bytes med vilkårlig adgang, som systemet ikke pålægger nogen yderligere struktur. Systemet ved ikke og er ligeglad med, om de bytes er et regneark, et foto eller en side i en database; strukturen hører til det program, der læser dem. POSIX afviser endda at skelne mellem tekstfiler og binære filer, men bemærker, at mange værktøjer kun giver meningsfuldt output på tekst.
Navnet ligger uden for filen. En mappe er en liste over poster, og hver post kobler et filnavn til
en fil. Et filnavn er en enkelt komponent, der må indeholde enhver byte undtagen skråstreg og
nulbyten, op til en grænse, som systemet fastsætter; et stinavn som /srv/site/index.html er den
kæde af navne, systemet følger for at nå frem. Fordi navnene bor i mapper, kan én fil have flere af
dem, og systemet fører en optælling. Når det sidste navn fjernes, og ingen proces længere har filen
åben, frigives pladsen.
Alt andet, systemet ved om en fil, er metadata, og en lang oversigt viser det meste:
$ ls -li notes.txt
1048577 -rw-r----- 2 ana staff 4096 Oct 16 09:14 notes.txt
Det første tal er filens serienummer, unikt inden for dens filsystem: det nummer er filen, og navnene peger blot på den. Derefter kommer rettighedsbittene for ejeren, gruppen og alle andre, antallet af navne, filen har, ejer og gruppe, størrelsen i bytes og tidspunktet for den seneste ændring af data. POSIX gemmer to tidspunkter mere ved siden af: den seneste adgang til data og den seneste ændring af filens status. Et program, der har åbnet en fil, holder en fildeskriptor, et lille heltal, som kun gælder i processen. Deskriptorerne 0, 1 og 2 er standardinput, standardoutput og standardfejl, og derfor kan en shell sende et programs output til en fil, uden at programmet ved det.
Hvorfor det betyder noget
Filer er den ældste grænseflade mellem programmer, der aldrig er blevet præsenteret for hinanden. Et værktøj skrevet for årtier siden kan give data videre til et, der blev skrevet i går, gennem en fil, uden nogen anden aftale end bytes og navn. Konfiguration, logge, eksporter, sikkerhedskopier og indholdet af de fleste websites rejser på den måde, så at holde filer troværdige er det meste af at holde et system troværdigt.
Metadataene er der, hvor de lumske problemer bor. Ændringstidspunktet fortæller, hvornår de bytes sidst blev skrevet, og det er en anden oplysning end, hvornår det, de siger, sidst blev ændret. De to skilles, i samme øjeblik et værktøj skriver en fil om med identisk indhold. Ejerskab gemmes som et tal, så den samme fil kan tilhøre en anden person på en anden maskine.
Så er der holdbarheden. En skrivning, der vender tilbage, har givet de bytes til styresystemet, som
kan holde dem i en cache. POSIX siger, at data i cachen når frem til lageret, når et program beder
om det med et kald som fsync, og at de kan komme derhen tidligere af sig selv, og standarden
advarer om, at efter et nedbrud kan senere operationer ligge på disken, mens tidligere mangler.
Endelig er en fil én kopi på én enhed, indtil nogen sørger for andet. Den eneste beskyttelse, der holder, uanset hvordan mediet svigter, er en ekstra kopi et andet sted, som er blevet læst tilbage.
Sådan ser det ud i praksis
Sitets sitemap fortalte engang søgemaskinerne, at 172 af dets 176 sider var ændret i samme øjeblik. Rettelsen sporede datoen tilbage til selve filen: hver sides dato kom fra filens ændringstidspunkt, og indholdseksporten skriver hver fil om ved hver kørsel, så én synkronisering stemplede hele sitet. Nu kommer datoen fra versionshistorikken gennem en fallback-kæde, der prøver et eksplicit felt, så commit-historikken og til sidst filen. Siden noterer fælden i den kæde: selve feltnavnet skal stå på listen, ellers læser generatoren det aldrig. En manglende dato lader feltet stå tomt i stedet for at rumme et gæt, og en ny synkronisering efter en måneds redigeringer rører nu otte filer ud af 186.
Virksomhedens sikkerhedskopier slutter med, at en fil bliver læst tilbage. En systemd-timer kører et databasedump, sender et krypteret, deduplikeret snapshot til en anden udbyders lager over SFTP, udtynder efter opbevaringspolitikken og kører et integritetstjek. Hver måned gendanner en øvelse en enkelt fil med kendt indhold og sammenligner den, så det, øvelsen afprøver, er selve gendannelsen. Selv adgangssætningen ligger i en fil, som enhederne læser. Supervisoren fortolker escape-tegn i miljøvariablernes værdier, så sendt den vej ville en omvendt skråstreg i adgangssætningen i al stilhed have ændret den, og det, der nåede frem, var ikke længere den adgangssætning, backuplageret blev oprettet med.
År forinden gik arbejdet ud på at redde filer, ofte den eneste kopi, fra hardware, der var gået i stykker: datagendannelse fra SD-kort, roterende harddiske, SSD’er, RAID-arrays, eksterne drev og Mac-systemer. Hver af dem går i stykker og giver sine data fra sig på sin egen måde, og et Mac-filsystem har sine egne særheder, så arbejdet handlede lige så meget om den rette tilgang til mediet som om nogen enkelt teknik. Målestokken var den enkle: filerne leveret tilbage i behold.
Hvor det går galt
Alle sider ser ændrede ud på én gang. En kopiering, en checkout, en gendannelse eller en eksport skriver filen om og nulstiller ændringstidspunktet, og alt længere nede i kæden, der stoler på det, ser en ændring, som aldrig skete. En kopiering, der bevarer tidspunkterne, gør det modsatte og skjuler en ændring, der faktisk skete. Tag indholdsdatoer fra indholdet eller fra versionshistorikken, og lad filens tidspunkt betyde det, det betyder.
En læser finder en halv fil. Et program, der skriver en fil om på stedet, efterlader et vindue,
hvor en anden proces, eller den næste opstart, ser en del af den gamle version og en del af den nye.
Skriv en midlertidig fil i samme mappe, kald fsync på den, og omdøb den derefter oven på
originalen. POSIX kræver, at det navn, der erstattes, forbliver synligt under hele omdøbningen og
peger på enten den gamle fil eller den nye.
Et script snubler over et lovligt navn. Et filnavn kan indeholde mellemrum, linjeskift og en
indledende bindestreg, og et script, der deler navne ved mellemrum eller giver dem til en kommando
uden anførselstegn, rammer de forkerte filer. POSIX råder selv til at undgå en indledende bindestreg
og til at holde sig til bogstaver, cifre, punktum, understreg og bindestreg i navne, der skal kunne
flyttes. Sæt anførselstegn om hver variabel, og afslut tilvalgslisten med -- før en liste af
navne.
En hemmelig fil kan læses af alle. Rettighedsbittene på en ny fil kommer fra standardværdierne i den proces, der oprettede den, og de lader som regel gruppen og andre læse. En nøgle eller en adgangssætning, der skrives på den måde, deles med hver eneste konto på værten. Opret hemmelige filer med rettigheder kun for ejeren fra begyndelsen i stedet for at stramme dem bagefter.
Læs mere
- NIST CSRC-ordliste: file — definitionerne fra NIST’s sikkerhedspublikationer, hver med det dokument, den stammer fra.
- POSIX.1-2024 Base Definitions: Definitions — den formelle betydning af fil, almindelig fil, filnavn, stinavn, mappepost og fildeskriptor.
- POSIX.1-2024 Base Definitions: General Concepts — rettigheder, filens tre tidspunkter, flytbare filnavne og hvad et nedbrud kan efterlade i cachen.
- POSIX.1-2024: rename() — garantien for, at et navn, der erstattes, hele tiden peger på enten den gamle fil eller den nye, som sikker gemning bygger på.