Linux E X P R E S

Facebook

Jak spouštět v Linuxu libovolné soubory

Linux

Že lze v Linuxu spouštět programy pro Linux, ví každý uživatel. Ti pokročilejší znají i skripty. Ale Linux umí stejně jednoduše spouštět prakticky libovolné soubory – například javové archivy nebo programy pro Windows. 


Jak Linux spouští programy

Co to vlastně znamená, když se řekne „spuštění programu“? V Linuxu je potřeba vykonat dva kroky. Nejdřív se vytvoří nový proces – ten je zpočátku kopií nějakého existujícího procesu a liší se jen identifikátorem (PID). Tady to může někdy i skončit. Děje se tak například tehdy, pokud si běžící proces vytváří své kopie, které pro něj vykonávají nějakou práci (takto v určité konfiguraci funguje například webový server Apache).

Většinou ale proběhne i druhá fáze, kdy se spustí nějaký nový program. Jádro si otevře soubor s programem a vybere spouštěč, který se pro spuštění programu použije. Klasické programy (zkompilované do strojového kódu; v Linuxu se standardně používá formát ELF) se namapují do paměti, připojí se k nim potřebné knihovny a začne se vykonávat jejich kód.

Uživatel musí mít samozřejmě k souboru práva ke spuštění. Bez nich jádro spuštění programu nedovolí.

Pokud je spouštěným programem skript, jádro si zjistí požadovaný interpret (cesta k němu je ve skriptu uvedena), ten spustí (viz výše) a skript mu předá. Obecně ale mohou být soubory ke spuštění i jiné a jádro pak vybere jiný spouštěč, je-li k dispozici.

O tom, jaký spouštěč se použije, se jádro rozhoduje podle názvu souboru nebo jeho obsahu. Například klasický spustitelný program obsahuje určitou „signaturu“, podle níž Linux pozná, že je to tento typ souboru. Skript se pozná podle znaků #! na začátku souboru. Za nimi pak následuje cesta k interpretu a případně argumenty, které se mají interpretu předat – viz příklad:

!# /bin/sh -e
exit 0

Tento primitivní skript bude spuštěn interpretem sh a hned skončí s nulových návratovým kódem (úspěšný konec).

Spouštěč binfmt_misc

V Linuxu je kromě specializovaných spouštěčů k dispozici i jeden obecný (binfmt_misc), s jehož pomocí si lze nastavit spouštění souborů prakticky libovolného typu. Soubory lze identifikovat buď podle přípony, nebo podle obsahu (ale ne podle obojího současně). Pro soubor se pak spustí příslušný interpret (jako pro skripty).

Přípona je celkem jasná, v případě obsahu se používá „magické číslo“ umístěné na nějaké pevné pozici v souboru. U binárních souborů to často není problém, u souborů textového charakteru to problém může být, protože neexistuje pevná pozice, na které by se nacházela nějaká data (přestože je třeba soubor XML uvozen konkrétní posloupností znaků, ještě před ní může být například typ dokumentu, odřádkování apod.).

Jak to funguje? Nejdřív je potřeba, aby byl v jádře načten modul binfmt_misc. V některých distribucích je již ve výchozím stavu nainstalován a načítán, jinde je potřeba příslušný balíček doinstalovat ručně (např. v Debianu, Ubuntu a dalších distribucích této větve se jmenuje binfmt-support).

Dalším krokem je konfigurace spouštěče. Modul binfmt_misc si vytváří v souborovém systému procfs (připojeném do adresáře /proc) svůj malý podstrom, který slouží k ovládání spouštěče. Najdete ho v adresáři /proc/sys/fs/binfmt_misc. Jeho obsah může vypadat třeba takto (příklad z distribuce Linux Mint 18.1):

cli 
jar 
python2.7
python3.5
register
status

Začněme od konce. Soubor status obsahuje informaci, zda je spouštěč povolen; zároveň ho lze pomocí zápisu znaků 0 a 1 vypnout, resp. zapnout. Soubor register slouží k registraci typů souborů – do něj se zapisují registrační řetězce. Zbývající soubory už pak příslušejí jednotlivým typům zaregistrovaných souborů.

Když se do některého podíváte, uvidíte něco jako toto:

enabled
interpreter /usr/bin/python2.7
flags: 
offset 0
magic 03f30d0a

To znamená, že je spouštěč povolen, je pro něj použit daný interpret, nepoužívají se žádné příznaky, obsah se testuje na offsetu 0 a hledá se uvedené magické číslo. Uvedený příklad je pro spouštění zkompilovaných souborů jazyka Python 2.7. Pod názvem jar se skrývá spouštění javových archivů.

Jak si zaregistrovat typ souboru

Pokud si chcete zaregistrovat nový typ souboru pro spouštění, je potřeba nejdřív vědět, jak soubor poznat a čím ho spustit. Tak například budeme chtít spustit program mpg123 pro soubory ve formátu MP3. Jsou dvě možnosti, jak to zajistit. Lze vyjít z přípony názvu souboru nebo z magického čísla.

První možnost je jednodušší. Víme, že přípona je „mp3“. Takže už zbývá si jen připravit řetězec, který se pošle jádru k zaregistrování typu. Řetězec má tento obecný formát:

:name:type:offset:magic:mask:interpreter:flags

Takže pro MP3 bude vypadat nějak takto:

:MP3:E::mp3::/usr/bin/mpg123:

Název typu je jasný. Písmeno E říká, že se k rozlišení použije přípona názvu. Offset je prázdný, místo magického číslo se uvede přípona, maska opět prázdná, u interpretu je potřeba uvést celou absolutní cestu ke spustitelnému souboru. Příznaky nejsou využity.

Tento řetězec je potřeba uložit do souboru /proc/sys/fs/binfmt_misc/register (třeba příkazem echo). Tím se typ zaregistruje a zvukové soubory MP3 lze od této chvíle spouštět „přímo“, bez přemýšlení, čím se mají přehrát.

Pozor na to, že soubory musí mít nastaveno právo ke spuštění (což u souborů MP3 standardně nebývá)!

Jak by se spouštění nastavilo pomocí magického čísla? Příslušná čísla (signatury) lze najít například na Wikipedii. Ttentokrát budeme chtít přehrát formát OGG, který může mít různé přípony názvu, ale vždy stejné magické číslo. Přehrávat se bude programem mplayer. Takto bude vypadat řetězec:

:OGG:M:0:4F676753::/usr/bin/mplayer:

Za zmínku stojí písmeno M pro volbu magického čísla, následuje nulový offset a magické číslo formátu.

Řešení složitějších případů

Když budete podrobněji zkoumat signatury formátů, všimnete si, že stejný formát může mít více různých signatur – to je i případ formátu MP3, který se liší podle toho jestli má metadata IDv1 nebo IDv2, případně je zcela bez metadat. To lze vyřešit buď zaregistrováním více typů, nebo se dá rozpoznávání přesunout jinam. Totéž nás nemine v případech, které samotný modul nemůže vůbec vyřešit.

To „jinam“ znamená do interpretu run-detectors, který je součástí balíčku s modulem. Tento interpret bývá umístěn například v /usr/lib/binfmt-support. Tento interpret vznikl původně pro potřeby projektu Mono – vznikl totiž problém s tím, že spustitelné programy pro .NET mají stejou signaturu jako běžné spustitelné programy a nešlo tedy určit, zda se mají spouštět pomocí interpretu Mono nebo Wine. Na jeho fungování se podíváme někdy příště.

Diskuze (4) Nahoru