GNU/Linux >> Znalost Linux >  >> Linux

Co se přesně stane, když spustím soubor v prostředí Shell?

Takže jsem si myslel, že tomu rozumím dobře, ale provedl jsem test (v reakci na konverzaci, kde jsem s někým nesouhlasil) a zjistil jsem, že moje porozumění je chybné…

Co nejpodrobněji co se přesně stane, když spustím soubor v mém shellu? Mám na mysli, když napíšu:./somefile some arguments do mého shellu a stiskněte return (a somefile existuje v cwd a mám oprávnění ke čtení a spouštění pro nějaký soubor ) co se potom děje pod kapotou?

Myslel jsem odpověď byla:

  1. Shell provede systémové volání exec , předá cestu k nějakému souboru
  2. Jádro zkoumá nějaký soubor a podívá se na magické číslo souboru, aby zjistil, zda se jedná o formát, který procesor zvládne
  3. Pokud magické číslo udává, že soubor je ve formátu, který může procesor spustit, pak
    1. je vytvořen nový proces (se záznamem v tabulce procesů)
    2. nějaký soubor se čte/mapuje do paměti. Vytvoří se zásobník a provedení skočí na vstupní bod kódu somefile , s ARGV inicializován na pole parametrů (char** , ["nějaké","argumenty"] )
  4. Pokud je magické číslo shebang, pak exec() vytvoří nový proces jako výše, ale použitým spustitelným souborem je interpret, na který odkazuje shebang (např. /bin/bash nebo /bin/perl ) a nějaký soubor je předán STDIN
  5. Pokud soubor nemá platné magické číslo, objeví se chyba jako „neplatný soubor (špatné magické číslo):Chyba formátu Exec“

Někdo mi však řekl, že pokud je soubor prostý text, pak se shell pokusí provést příkazy (jako bych napsal bash somefile ). Nevěřil jsem tomu, ale prostě jsem to zkusil a bylo to správné. Takže mám zjevně nějaké mylné představy o tom, co se tu vlastně děje, a rád bych porozuměl mechanikám.

Co přesně se stane, když spustím soubor v mém shellu? (pokud jde o podrobnosti, které jsou rozumné…)

Přijatá odpověď:

Definitivní odpovědí na otázku „jak se spouštějí programy“ na Linuxu je dvojice článků na LWN.net nazvaných, překvapivě, Jak se spouštějí programy a Jak se spouštějí programy:binární soubory ELF. První článek se skriptům věnuje stručně. (Přesně vzato je definitivní odpověď ve zdrojovém kódu, ale tyto články se snáze čtou a poskytují odkazy na zdrojový kód.)

Trocha experimentování ukazuje, že jste to do značné míry vystihli správně a že spuštění souboru obsahujícího jednoduchý seznam příkazů bez shebangu musí zvládnout shell. Manuová stránka execve(2) obsahuje zdrojový kód pro testovací program, execve; použijeme to, abychom viděli, co se stane bez shellu. Nejprve napište testovací skript testscr1 , obsahující

#!/bin/sh

pstree

a další, testscr2 , obsahující pouze

pstree

Udělejte je oba spustitelnými a ověřte, že oba běží z prostředí shell:

chmod u+x testscr[12]
./testscr1 | less
./testscr2 | less

Nyní to zkuste znovu pomocí execve (za předpokladu, že jste jej vytvořili v aktuálním adresáři):

./execve ./testscr1
./execve ./testscr2

testscr1 stále běží, ale testscr2 produkuje

execve: Exec format error

To ukazuje, že shell zpracovává testscr2 jinak. Nezpracovává však samotný skript, stále používá /bin/sh udělat to; to lze ověřit pomocí potrubí testscr2 na méně :

./testscr2 | less -ppstree

V mém systému dostávám

    |-gnome-terminal--+-4*[zsh]
    |                 |-zsh-+-less
    |                 |     `-sh---pstree

Jak můžete vidět, je tu shell, který jsem používal, zsh , který začal méně , a druhý shell, prostý sh (pomlčka na mém systému), ke spuštění skriptu, který spustil pstree . V zsh toto řeší zexecve v Src/exec.c :shell používá execve(2) pokusit se spustit příkaz, a pokud se to nezdaří, přečte soubor, aby zjistil, zda má shebang, a podle toho jej zpracuje (což jádro také udělá), a pokud se to nezdaří, pokusí se spustit soubor s sh , pokud nepřečte žádný nulový bajt ze souboru:

        for (t0 = 0; t0 != ct; t0++)
            if (!execvebuf[t0])
                break;
        if (t0 == ct) {
            argv[-1] = "sh";
            winch_unblock();
            execve("/bin/sh", argv - 1, newenvp);
        }

bash má stejné chování, implementované v execute_cmd.c s užitečným komentářem (jak poukázal taliezin):

Proveďte jednoduchý příkaz, který je, doufejme, definován v souboru na disku
někde.

  1. fork ()
  2. připojit potrubí
  3. vyhledejte příkaz
  4. provádět přesměrování
  5. execve ()
  6. Pokud execve selhal, zjistěte, zda má soubor nastavený spustitelný režim.
    Pokud ano a nejedná se o adresář, spusťte jeho obsah jako
    skript shellu.

POSIX definuje sadu funkcí, známou jako exec(3) funkce, které obalují execve(2) a poskytovat také tuto funkci; podrobnosti viz Muruova odpověď. Na Linuxu jsou alespoň tyto funkce implementovány knihovnou C, nikoli jádrem.

Související:účel klíčového slova „do“ v Bash pro smyčky?
Linux
  1. nelze spustit binární soubor při pokusu o spuštění skriptu shellu na linuxu

  2. Co se stane, když se vlákno rozvětvuje?

  3. Co přesně určuje, zda je úloha na pozadí při opuštění shellu zabita nebo zabita?

  1. Co se stane, když spustím příkaz Cat /proc/cpuinfo?

  2. Co je lepkavý bit v souborových systémech UNIX? Kdy se používá?

  3. Co je výchozí shell Busybox?

  1. Linux – Co se stane, když Rsync bez cílové cesty?

  2. Co se stane, když je překročen limit šířky pásma?

  3. Co se stane s popisovačem otevřeného souboru v systému Linux, pokud se označený soubor přesune nebo odstraní