Gibt es eine Möglichkeit, einen Prozess-Exit-Status zu erhalten, nachdem unter Linux viele weitere Befehle ausgegeben wurden?

7

Wenn ich viele Befehle habe, die ich ausgegeben habe, und ich möchte den Beendigungsstatus eines Prozesses, der beendet wurde, beispielsweise vor 100 Befehlen. Gibt es eine Struktur, einen Dateispeicherort oder eine Variable unter Linux, auf die ich auf alle beendeten Prozesse zugreifen und Informationen darüber anzeigen kann?

mutant_city
quelle

Antworten:

3

Wenn die BSD-Prozessabrechnung accton onmit GNU acct6.6.3 oder höher aktiviert war ( ausgestellt wurde), können Sie diese Informationen von lastcomm --debugoder dump-acct /var/log/account/pact(oder überall dort abrufen, wo die Prozessabrechnungsdaten auf Ihrem System gespeichert sind) abrufen .

$ perl -e 'Ausfahrt 123'
$ lastcomm --debug | grep perl
AKTUELLE AUFNAHME: perl | v3 | 0,00 | 0,00 | 0,00 | 1000 | 1000 | 26328.00 | 0,00 | 332 | 8530 | |     123 | pts / 1 | Mi Sep 19 20:21:26 2018
$ dump-acct / var / log / account / pacct | grep perl
perl | v3 | 0,00 | 0,00 | 0,00 | 1000 | 1000 | 26328.00 | 0,00 | 332 | 8530 | |     123 | pts / 1 | Mi Sep 19 20:21:26 2018

Sie erhalten den Exit-Code im vorletzten Feld und im vorletzten Feld, ob er getötet wurde oder nicht (aber nicht die Signalnummer, siehe die Antwort von @ mosvy ).

Stéphane Chazelas
quelle
2

Wenn Sie auf debian sind, können Sie das acctInstallationspaket , um Prozess - Accounting zu aktivieren, aber feststellen , dass weder lastcomm --debugnoch dump-acctzeigt etwas wie der Exit - Status oder das Signal , das einen Prozess beendet.

Wenn Sie diese Daten abrufen möchten, können Sie ein Skript wie das folgende verwenden:

$ cat pacct.pl
#! /usr/bin/perl
use strict;
use Config;
printf "%-7s %6s %6s  %8s %8s  %s\n",
        'STATUS', 'UID', 'PID', 'BTIME', 'ETIME', 'COMMAND';
my @sig = split ' ', $Config{sig_name};
$/ = \64;
while(<>){
        my @f = unpack 'CCSL6fS8A*', $_;
        my ($flag, $version, $tty, $exitcode, $uid, $gid, $pid, $ppid,
                $btime, $etime, $utime, $stime, $mem, $io, $rw,
                $minflt, $majflt, $swaps, $cmd) = @f;
        my $s = $exitcode & 0x7f;
        my $status = $s ?  "SIG$sig[$s]" : $exitcode >> 8;
        printf "%-7s %6d %6d  %02d:%02d:%02d %8.2f  %-16s\n",
                $status, $uid, $pid,
                (localtime $btime)[2,1,0],
                $etime / 100,
                $cmd;
}

# perl pacct.pl /var/log/account/pacct
# tail -f /var/log/account/pacct | perl pacct.pl

Dies setzt die Version 3 des Protokolldateiformats voraus - siehe acct.h.

Beachten Sie jedoch, dass dies nicht so nützlich ist, da nur der Prozess- / Thread-Name in der Protokolldatei enthalten ist (dh der Basisname der ausführbaren Datei, der auf 15 Byte abgeschnitten ist und mit dem leicht gefälscht werden kann prctl(PR_SET_NAME)), nicht der Pfad des ausführbare Datei oder die Argumente, mit denen es aufgerufen wurde.

Wenn Sie erweitern möchten , dass Skript auch die Anzeige stime, utimeetc Felder, kann dies nützlich sein:

# translate comp_t to float
# utime, stime, mem, minflt, majflt are in the comp_t format
# io, rw, swaps are never set; they're purely decorative
sub comp2f {
        my $m = $_[0] & 0x1fff; my $e = $_[0] >> 13; $m * 8 ** $e;
}

Hinweis: Anstatt das acctPaket zu installieren , können Sie die Prozessabrechnung auch aktivieren mit:

# mkdir /var/log/account
# perl -e 'require "syscall.ph"; my $f = shift;
  open my $h, ">>", $f or die "open >>$f: $!" if $f;
  $! = -syscall SYS_acct(), $f // 0 and die "acct $f: $!";
' /var/log/account/pacct
Mosvy
quelle
Auf welcher Version von Debian haben Sie lastcomm --debug / dump-acct ausprobiert? Es funktionierte für mich auf Debian instabil und auf Ubuntu 18.04 (obwohl es nicht die Signalnummer für die Prozesse gibt, die getötet wurden)
Stéphane Chazelas
Beachten Sie, dass es sich nicht um den Befehlsnamen handelt , sondern um den Prozessnamen (geändert bei jedem execve()Aufruf des Prozesses auf die ersten 15 Bytes des Basisnamens der ausgeführten Datei). Sie können es nicht durch Überschreiben ändern argv[0], sondern mit prctl(PR_SET_NAME, newname)oder execve(). Wenn Sie dies tun env sh -c 'exec bash -c "exit 123"', ist dies ein Prozess, der der Reihe nach ausgeführt wird env, shund bash. Das Pacct-Protokoll zeigt nur einen Eintrag für bash(den Namen des Prozesses zum Zeitpunkt des
Stéphane Chazelas
@ StéphaneChazelas Strecke (stabil)
Mosvy
Ja, Sie benötigen GNU acct 6.6.3 oder höher. Stretch hat 6.6.2.
Stéphane Chazelas
-2

Das

  set -o pipefail 

ist ziemlich nah an dem, was Sie wollen; es wird

Eine Pipeline wird erst abgeschlossen, wenn alle Komponenten der Pipeline abgeschlossen sind, und der Rückgabewert ist der Wert des letzten fehlgeschlagenen Befehls ungleich Null oder Null, wenn kein Befehl fehlgeschlagen ist.

Wenn Sie also 40 Befehle zusammen geleitet haben und der dritte Befehl einen Rückkehrcode von 8 ergibt und der Rest erfolgreich abgeschlossen wurde, wäre der Gesamtrückgabecode 8. Es wäre schwierig herauszufinden, welcher Befehl den schlechten Rückkehrcode gegeben hat.

Mark Stewart
quelle
1
Es gibt keinen Hinweis darauf, dass die Befehle als Teil derselben Pipeline ausgegeben werden.
Kusalananda
Guter Punkt; Ich habe die Frage nicht genau genug gelesen, aber ich werde die Antwort für den Fall hinterlassen, dass jemand davon profitiert. Es war eine meiner schönen Überraschungen, als ich von Solaris zu Linux wechselte.
Mark Stewart
2
Ja Danke. Es gibt auch eine Umgebungsvariable PIPESTATUS [0] für Pipelines. Dies wäre nur im Allgemeinen.
mutant_city