GNU/Linux >> Znalost Linux >  >> Linux

Bash:Proč se nadřazený skript neukončí na SIGINT, když podřízený skript zachytí SIGINT?

Nová odpověď:

Tato otázka je mnohem zajímavější, než jsem původně tušil. Odpověď je v podstatě uvedena zde:

Co se stane se SIGINTem (^C), když je odeslán do skriptu v perlu obsahujícím děti?

Zde je relevantní hláška. Uvědomuji si, že nepoužíváte Perl, ale předpokládám, že Bash používá konvenci C.

Vestavěná systémová funkce Perlu funguje stejně jako funkce C system(3) ze standardní knihovny C, pokud jde o signály. Pokud používáte Perlovu verzi system() nebo pipe open nebo backtick, pak nadřazený — jeden volající systém spíše než ten, který se nazývá byit – bude IGNOROVAT jakýkoli SIGINT a SIGQUIT, zatímco děti běží.

Toto vysvětlení je to nejlepší, co jsem viděl o různých možnostech, které lze provést. Také říká, že Bash používá přístup WCE. To znamená, že když nadřazený proces obdrží SIGINT, čeká, dokud se nevrátí jeho podřízený proces. Pokud tento obsluhovaný proces opustí SIGINT, ukončí se také pomocí SIGINT. Pokud dítě odešlo jiným způsobem, ignoruje SIGINT.

Existuje také způsob, jak může volající shell zjistit, zda volaný program skončil na SIGINT a zda ignoroval SIGINT (nebo jej použil pro jiné účely). Stejně jako ve způsobu WUE, shell čeká na dokončení dítěte. Zjistí, zda byl program ukončen na SIGINT, a pokud ano, přeruší skript. Pokud se program ukončí jiným způsobem, skript bude pokračovat. Ve zbytku tohoto dokumentu budu způsob, jak věci dělat, nazývat „WCE“ (pro „čekání a kooperativní ukončení“).

Nemohu na to najít odkaz na Bash man page, ale budu dál hledat v informačních dokumentech. Ale jsem si na 99% jistý, že toto je správná odpověď.

Stará odpověď:

Nenulový stav ukončení z příkazu ve skriptu Bash neukončí program. Pokud uděláte echo $? po ./script2.sh zobrazí se 130. Skript můžete ukončit pomocí set -e jak navrhuje phs.

$ help set
...
-e  Exit immediately if a command exits with a non-zero status.

Druhá část aktualizované odpovědi @seanmcl je správná a odkaz na http://www.cons.org/cracauer/sigint.html je opravdu dobré si pečlivě přečíst.

Z tohoto odkazu "Nemůžete 'předstírat' správný výstupní stav pomocí exit(3) se speciální číselnou hodnotou, i když hledáte číselnou hodnotu pro svůj systém ". O to se ve skutečnosti pokouší @Hermann Speiche's script2.sh."

Jednou z odpovědí je upravit handler funkce v script2.sh následovně:

function handler {
  # ... do stuff ...
  trap INT
  kill -2 $$
}

To efektivně odstraní obsluhu signálu a "znovu hodí" SIGINT, což způsobí, že proces bash skončí s příslušnými příznaky, takže jeho nadřazený proces bash pak správně zpracuje SIGINT, který mu byl původně odeslán. Tímto způsobem pomocí set -e nebo jakýkoli jiný hack není ve skutečnosti vyžadován.

Za zmínku také stojí, že pokud máte spustitelný soubor, který se při odeslání SIGINT chová nesprávně (neodpovídá „Jak být správný program“ ve výše uvedeném odkazu, např. ukončí se s normálním návratovým kódem), jeden způsob Jak to obejít, je zabalit volání tohoto procesu do skriptu, jako je tento:

#!/bin/bash

function handler {
  trap INT
  kill -2 $$
}

trap handler INT
badprocess "[email protected]"

Linux
  1. Proč není Sigint propagován do podřízeného procesu, když je odeslán jeho nadřazenému procesu?

  2. Proč překladový soubor Bash neobsahuje všechny chybové texty?

  3. Proč nefunguje automatické dokončování při zadávání názvu příkazu za „zdroj“?

  1. Příkaz Rm ve skriptu Bash nefunguje s proměnnou?

  2. Proč dokument Parent Shell Here nefunguje pro dílčí příkaz v Dash, ale funguje Bash?

  3. Proč „ukončit &“ nefunguje?

  1. Podřízený proces obdrží SIGINT rodiče

  2. Jakýkoli způsob, jak ukončit bash skript, ale ne opustit terminál

  3. Proč tento plášťový ropovod vystupuje?