GNU/Linux >> Znalost Linux >  >> Linux

Jak číst celý skript Shell před jeho spuštěním?

Obvykle, pokud upravujete skript, všechna použití skriptu jsou náchylná k chybám.

Pokud tomu dobře rozumím, bash (i jiné shelly?) čte skript postupně, takže pokud jste soubor skriptu upravili externě, začne číst nesprávné věci. Existuje nějaký způsob, jak tomu zabránit?

Příklad:

sleep 20

echo test

Pokud tento skript spustíte, bash přečte první řádek (řekněme 10 bajtů) a usne. Když se obnoví, může být ve skriptu různý obsah začínající na 10. bajtu. Možná jsem uprostřed řádku v novém skriptu. Spuštěný skript tak bude přerušen.

Přijatá odpověď:

Ano shelly a bash zejména dávejte pozor, abyste soubor četl jeden řádek po druhém, takže to funguje stejně, jako když jej používáte interaktivně.

Všimnete si, že když soubor nelze vyhledat (jako potrubí), bash dokonce čte jeden bajt po druhém, abyste si byli jisti, že nečte za \n charakter. Když je soubor vyhledatelný, optimalizuje se čtením celých bloků najednou, ale přejde zpět za \n .

To znamená, že můžete dělat věci jako:

bash << \EOF
read var
var's content
echo "$var"
EOF

Nebo pište skripty, které se samy aktualizují. Což byste nemohli udělat, kdyby vám to nedávalo tuto záruku.

Nyní je vzácné, že chcete dělat takové věci, a jak jste zjistili, tato funkce má tendenci překážet častěji, než je užitečná.

Abyste se tomu vyhnuli, můžete se pokusit ujistit se, že soubor neupravíte na místě (například upravíte kopii a přesunete kopii na místo (jako sed -i nebo perl -pi a někteří editoři to například dělají)).

Nebo můžete napsat svůj skript jako:

{
  sleep 20
  echo test
}; exit

(Všimněte si, že je důležité, aby exit být na stejném řádku jako }; i když byste ho také mohli vložit do závorek těsně před zavíracím.

nebo:

main() {
  sleep 20
  echo test
}
main "[email protected]"; exit

Shell bude muset číst skript až do exit než začnete něco dělat. To zajišťuje, že shell nebude znovu číst ze skriptu.

To znamená, že celý skript bude uložen v paměti.

To může také ovlivnit analýzu skriptu.

Například v bash :

export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'

Výstup by U+00E9 zakódovaný v UTF-8. Pokud jej však změníte na:

{
  export LC_ALL=fr_FR.UTF-8
  echo $'St\ue9phane'
}

\ue9 bude rozšířena ve znakové sadě, která byla platná v době, kdy byl příkaz analyzován, což je v tomto případě před export příkaz se provede.

Související:SSH – skript pro automatizaci scp v síti?

Všimněte si také, že pokud source aka . Pokud se používá příkaz, u některých shellů budete mít stejný problém se zdrojovými soubory.

To není případ bash ačkoli jehož source příkaz přečte soubor před jeho interpretací. Pokud píšete pro bash konkrétně byste to mohli skutečně využít přidáním na začátek skriptu:

if [[ ! $already_sourced ]]; then
  already_sourced=1
  source "$0"; exit
fi

(Na to bych se však nespoléhal, protože si dokážete představit budoucí verze bash mohl změnit toto chování, které lze v současnosti považovat za omezení (bash a AT&T ksh jsou jediné shelly podobné POSIXu, které se takto chovají, pokud lze říci) a already_sourced trik je trochu křehký, protože předpokládá, že proměnná není v prostředí, nemluvě o tom, že ovlivňuje obsah proměnné BASH_SOURCE)


Linux
  1. Jak používat šifrované heslo ve skriptu Linux Bash Shell

  2. Přizpůsobení prostředí Bash

  3. Jak získat externí IP adresu ve skriptu Shell?

  1. Jak zkontrolovat podřetězec v Shell Script Bash?

  2. Bash Script - Jak číst uživatelský vstup

  3. Jak BASH Shell načítá své konfigurační soubory v Linuxu

  1. Jak poznám název souboru skriptu ve skriptu Bash?

  2. Jak spustit skript shellu na konzole Unix nebo terminálu Mac?

  3. Jak číst předposlední řádek v souboru pomocí Bash?