Was awk's zurückgeben system()
sollte, ist schlecht spezifiziert .
Was bei awk
Implementierungen üblich zu sein scheint, ist, dass bei einem normalen Exit der Exit-Code (die an exit(3)
Modulo 256 übergebene Nummer ) zurückgegeben wird. Wenn der Shell-Prozess jedoch durch ein Signal beendet wird, gibt es viele verschiedene Verhaltensweisen.
Beachten Sie auch, dass die C-Funktion system(3)
zwar SIGINT (und SIGQUIT) im übergeordneten Element ignorieren soll, es jedoch (zumindest für mich) nicht sehr klar ist, dass die Anforderung auch für awk
's gilt system()
. Einige awk
Implementierungen (wie mawk
) sterben an diesem SIGINT (das ist auch das Verhalten, das ich gerne sehen würde, da ich nicht mag, dass meine STRG-C ignoriert wird, nur weil awk
zufällig die system()
Funktion ausgeführt wird), andere (wie gawk
oder traditionelle Implementierungen) Gewohnheit.
Beachten Sie auch, dass einige Shells einige dieser Signale abfangen und schließlich aufrufen können, exit()
was sich auf das Verhalten auswirken würde (siehe beispielsweise die Diskussion in den Kommentaren zur Bourne-Shell). Deshalb verwende ich exec
in den folgenden Beispielen, um die Shell aus der Schleife zu entfernen.
Für den Wert, der von einem SIGINT zurückgegeben wird system()
(es gibt noch mehr Variationen, wenn Sie close()
1 berücksichtigen ), sehen wir:
$ nawk 'BEGIN {print system("exec kill -s INT $$")}'
0.0078125
$ bwk-awk 'BEGIN {print system("exec kill -s INT $$")}'
0.0078125
$ mawk 'BEGIN {print system("exec kill -s INT $$")}'
130
$ gawk 'BEGIN {print system("exec kill -s INT $$")}'
0
0.0078125
Sein 2 / 256
(für einen SEGV
von 11
würde man 0,542969 ((128 + 11) / 256) erhalten, wenn ein Kern entleert wurde, andernfalls 0,0429688 (11/256)), nawk
das nawk
auf Solaris 10 oder 11 gefundene oder sein Linux-Port im Erbstück Werkzeugkasten, bwk-awk
wobei die awk
gepflegt von Brian Kernighan selbst (die K
in awk
) die Grundlage für die awk
auf einigen BSDs gefunden (hier getestet auf Debian GNU / Linux). /usr/xpg4/bin/awk
unter Solaris 11 verhält sich wie gawk
.
So basierend auf dem Wert s
von zurückgegeben system(3)
(eine Ganzzahl , wo die Bits 0 bis 6 ist die Signalnummer sind, Bit 7 das Kern-Bit, und Bit 8 bis 15 der Beendigungscode), awk
‚s system()
obigen gibt entweder:
s / 256
(traditionelle awk
Implementierungen),
int(s/256)
( gawk
),
- oder in
mawk
, die gleiche Transformation, wie sie beispielsweise von Shells wie der Bourne- oder C-Shell durchgeführt wird ( (s&127)+128
wenn sie getötet werden, s>>8
andernfalls), außer dass, wenn ein Core entleert wird, Sie (s&127)+256
stattdessen (s&127)+128
(der Wert ist (s&255)+128
) erhalten.
Hier könnten Sie stattdessen Folgendes tun:
awk 'BEGIN{print system("trap exit\\ 1 INT; sleep 10")}'
Aber es würde immer noch dazu führen awk
, mit einigen awk
Implementierungen wie getötet zu werden mawk
. Wenn Ihr sh
ist bash
oder yash
, könnten Sie tun:
awk 'BEGIN{print system("set -m; sleep 10; exit")}'
Wird sleep
also in einer eigenen Prozessgruppe ausgeführt (und nur es erhält das SIGINT).
Eine andere Alternative könnte darin bestehen, SIGINT vor dem Aufruf zu ignorieren awk
. Die meisten Shells (und das ist eine POSIX-Anforderung) können einen Signalhandler jedoch nicht ändern, wenn das Signal beim Start bereits ignoriert wurde. Also Dinge wie:
(
trap '' INT
awk 'BEGIN{print system("trap exit\\ 1 INT; sleep 10; exit")}'
)
Wird nicht funktionieren. zsh
hat diese (selbstverschuldete) Einschränkung jedoch nicht. Wenn Sie also wissen, dass sie zsh
verfügbar ist, können Sie Folgendes tun:
(
trap '' INT
awk 'BEGIN{print system("exec zsh -c \"TRAPINT() exit 1; sleep 10\"")}'
)
Welche funktionieren würde , ob awk
ist mawk
, gawk
oder eine andere und würde vermieden , mit Auftragssteuerung zu Chaos mit. An dieser Stelle lohnt es sich jedoch, die Verwendung von perl
/ python
/ ruby
... in Betracht zu ziehen, anstatt awk
die Signalverarbeitung an Ihre Bedürfnisse anzupassen.
Anmerkungen
1 Nach close()
einer Pipeline wie in:
awk 'BEGIN {cmd = "kill -s INT $$"; cmd | getline; print close(cmd)}'
Erstens ^C
unterbricht dieses Mal awk
alle Implementierungen, die ich versucht habe (es gibt keine solche Anforderung, SIGINT / SIGQUIT für popen(3)
/ zu ignorieren pclose(3)
(ein natürlicher Weg, dies zu implementieren getline
), wie es für ist system(3)
).
Aber wenn es um den Exit-Status geht (wo s
ist der von pclose(3)
/ waitpid(2)
like für system()
oben zurückgegebene Wert ), sehen wir:
- Solaris
nawk
: funktioniert nicht, so kann man close()
in Solaris nicht anrufen nawk
.
/usr/xpg4/bin/awk
unter Solaris. Gibt immer 0 zurück, auch wenn exit(1)
der Prozess abgeschlossen ist. Offensichtlich ein Konformitätsfehler.
gawk
und bwk-awk
: gibt s
( exit 1
gibt 256, getötet von SIGINT ergibt 2, getötet von einem SIGSEGV von 11 mit Kern ergibt 139).
mawk
: wie für system()
, sieht aus wie mawk
ist die einzige Implementierung, die darüber nachgedacht hat.