DB2 ist ein Produkt der
IBM Corporation. Bitte Copyright- und Trademark-Hinweise beachten!
#!/usr/local/bin/perl -w
################################################################################
# xmpTerm.pl - Display oder Terminate DB2 Application Threads
# Called by - Command Level oder DBA Scripts
# Calls - xmpPerl.pm - xmp DBA Perl Package
# Getopt - Argument Verwaltung
# Env - Zugriff auf Umgebungsvariablen
# English - Aliase für Perl Variablen
# Optionen - xmpTerm.pl -d db|*
# -l Display Threads
# -t id|* Terminate Thread(s)
#-------------------------------------------------------------------------------
# Autor - GR /05.01.00 - V1.0 erste Version
# Changes - GR /23.08.00 - V1.1 Terminate * bedeutet DEACTIVATE DB
# GR /11.09.00 - V1.2 winzige Text-Korrekturen
# GR /26.01.01 - V1.3 Terminate nur von Threads lokaler Datenbanken,
# Änderung von Kommentaren
# GR /17.07.01 - V1.4 Anpassung wg. DB2 V7.1, dazu auch neues xmpPerl.pm
# GR /11.12.01 - V1.5 Logging bei -t
#-------------------------------------------------------------------------------
# Comments - PERL5LIB Environment Variable muss auf Perl Module Pfad zeigen!
# Bei Versionswechsel ist die Gültigkeit der Annahmen zu überprüfen!
# - Die Angabe * kann gelegentlich zu Problemen führen: * wird gegen
# Dateinamen aus PWD substituiert. Stattdessen '*' angeben!
################################################################################
################################################################################
# Modules
################################################################################
use strict;
use Getopt::Std;
use vars qw($opt_d $opt_l $opt_t);
use xmpPerl;
use Env;
use English;
################################################################################
# Declare/Init
################################################################################
my $VER = "1.5";
my $work = "";# for TS List
my @work;# for TS List
my $work2 = "";# for Container List
my @work2;# for Container List
my $var;
my $val;
my $f_found;# Flag: found
my $db= 0;# no. of Databases
my %dbname= ();# Databases
my %dbtype= ();# Entry Type
my $t= 0;# no. of Threads
my %t_authid = (); my $f1="";# Auth ID
my %t_applname = (); my $f2="";# Application Name
my %t_id= (); my $f3="";# Thread ID
my %t_applid= (); my $f4;# Application ID
my %t_seq = (); my $f5;# Sequence
my %t_agentno = (); my $f6;# Number of Agents
my %t_node = (); my $f7;# Coordinator Node
my %t_pid= (); my $f8;# Coordinator PID
my %t_status= (); my $f9;# Status
my %t_statchgtm= (); my $fa;# Status Change Time
my %t_dbname= (); my $fb;# Database Name
my %t_path= (); my $fc;# DB Path
my $DB2Version = xmpPerl::getDB2Version;# akt. DB2 Version
################################################################################
# Ausgabe-Formate
################################################################################
format KOPF =
--------------------------------------------------------------------------------
------------------------ LIST OF DB2 THREADS -----------------------------------
DBNAME--------------------------------------------------------------------------
.
format ZEILE =
@<<<<<<<*ID.....: @<<<<<<< Path..: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$fb, $f3, $fc,
PID....: @<<<<<<< Node..: @>>>> Seq-No: @>>> Agents: @<<<<<<<<
$f8, $f7, $f5, $f6,
Auth-ID: @<<<<<<< Applic: @<<<<<<<<<<<<<<<<<<< Status: @<<<<<<<<<<<<<<<
$f1, $f2, $f9,
Appl-ID: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Status Change: @<<<<<<<<<<<<<<<
$f4, $fa
.
################################################################################
# Argumente/Options prüfen
################################################################################
getopts("d:lt:");
if (! defined $opt_d ){# Datenbank
$opt_d = "*";
}
if ((! defined $opt_l )and# List Option
(! defined $opt_t ) ){# Term Option
$opt_l = "";# List Option ist Default
}
if ((defined $opt_t ) and # Terminate requested
($opt_t ne "*") and# kein * drin
($opt_t !~ /[1234567890]/) ) {# nicht numerisch
print "$0 - bei -t *|nn angeben, also alle oder bestimmte Thread ID\n";
SaySyntax();
}
$opt_d = uc $opt_d;# uppercase Datenbank
################################################################################
# Check DB2 Existenz und Informationsblock ausgeben
################################################################################
xmpPerl::chkDB2();
xmpPerl::prtHeaderDB2("$0 - List/Terminate DB2 Threads - Version $VER");
print "Database ....................: $opt_d\n";
if (defined $opt_t) {
print "Terminate Threads ...........: $opt_t\n";
}
################################################################################
# DB2 List Database Directory wg. Name
################################################################################
#$work = xmpPerl::doCmdOut("db2 list db directory | grep -i 'database alias' | sort");
$work = xmpPerl::doCmdOut("db2 list db directory | egrep -i 'database alias|entry type'");
undef $/;
@work = split("\n",$work);
#print "$#work lines returned from DB2 List db dir Command.\n";
if ($work =~ "not found") {
die ">>> DB2 Commands (z.B. list db dir) nicht ausführbar!\n".
">>> Meldung: $work\n".
">>> ABEND ";
}
print "Databases im Directory ......: ";
foreach $work (@work) {
($var,$val) = split(" = ",$work);
if ($var =~ "alias") {
$db++;
$dbname{$db} = xmpPerl::trim($val);# Datenbank in Stack legen
#print $dbname{$db}." ";
}
if ($var =~ "entry type") {
$dbtype{$db} = lc xmpPerl::trim($val);# DB Type in Stack legen
print $dbname{$db}."(".$dbtype{$db}.") ";
}
}
print "\n";
if ($db == 0) {
die ">>> Diese DB2 System enthält keine Databases!\n".
">>> ABEND ";
}
################################################################################
# Wenn Database-Name als Argument angegeben, Namen prüfen
################################################################################
if ($opt_d ne "*") {
$work = $db;
$f_found = 0;
for ($db = 1; $db <= $work; $db++) {
if ($dbname{$db} eq $opt_d) {
$f_found = 1;
}
}
if ($f_found==0) {
die ">>> Diese Database $opt_d existiert nicht in diesem DB2 System!\n".
">>> ABEND ";
}
}
################################################################################
# Display Threads
################################################################################
if (defined $opt_l) {
GetThreads();
print "Current Threads at Instance : $t\n";
ReportThreads();
}
################################################################################
# Terminate Threads
################################################################################
if (defined $opt_t) {
########################################################################
# Write informational message to log file
########################################################################
xmpPerl::LogLine("DBA I ".$0." $< $opt_d $opt_t");
########################################################################
# Current Threads
########################################################################
GetThreads();
########################################################################
# Alle Threads abarbeiten
########################################################################
$work = $t;
for ($t = 1; $t <= $work; $t++) {
################################################################
# Bestimmter Thread oder alle Threads in allen DB's oder bestimmter DB
################################################################
#print "XXX ".$t_id{$t}." ".$t_dbname{$t}." XXXX\n";
if (( ($opt_t eq "*")
or ($t_id{$t} == $opt_t) )
and ( ($opt_d eq "*")
or ($t_dbname{$t} eq $opt_d ) ) ){
ForceThread($t_id{$t});
}
}
########################################################################
# Wenn alle Threads forced (alle überhaupt oder einer DB)
########################################################################
if ($opt_t eq "*"){
DeactivateDatabase();
}
########################################################################
# Buffer Flush
########################################################################
$work = xmpPerl::doCmdOut("db2 terminate");
#print "AAAAA $work\n";
}
################################################################################
# Display Threads erneut nach Terminate Threads
################################################################################
if ((defined $opt_l) and
(defined $opt_t)) {
GetThreads();
ReportThreads();
}
print "***Ende***\n";
exit 0;
#################################################################################
########################################################## Sub Routines #########
# SaySyntax #####################################################################
sub SaySyntax {
die "Usage: [perl] $0 -d [db|*] [-l] [-t id|*] ]\n".
"-d db|* database name\n".
"-l display thread(s) (default option)\n".
"-t id|*terminate thread(s)\n".
" Comment: Use '*' for * if experiencing problems using args.".
"abends";
}
################################################################################
# Alle oder nur best. DB-Threads ermitteln und Daten intern speichern
################################################################################
sub GetThreads {
my $work;
my $work2;
my $startpos = 9;# Dflt. Start
$t = 0;
########################################################################
# Starting position in DB2 command output is version-dependent!
########################################################################
if ($DB2Version =~ "5") {$startpos=9}# Version 6 17.07.2001
if ($DB2Version =~ "6") {$startpos=9}# Version 6 17.07.2001
if ($DB2Version =~ "7") {$startpos=31}# Version 7 17.07.2001
########################################################################
# DB2 List Applications show detail
########################################################################
$work = xmpPerl::doCmdOut("db2 list applications show detail");
undef $/;
@work = split("\n",$work);
#print "$#work lines returned from DB2 List Applications Command.\n";
if ($#work == 0) {return}
$f_found = 0;
foreach $work (@work) {
#($f1,$f2,$f3,$f4,$f5,$f6,$f7,$f7,$f9,$fa,$fb,$fc) = split(" ",$work);
if (length($work) > 0) {
########################################################
# Diese folgenden Bedingungen sind Versions-abhängig!
########################################################
$f1 = substr($work,0,8);# Authid
$f2 = substr($work,$startpos,20);# Appl. Name
$f3 = substr($work,$startpos+21,10);# Appl. Handle
$f4 = substr($work,$startpos+32,30);# Appl. ID
$f5 = substr($work,$startpos+63,4);# Seq. No
$f6 = substr($work,$startpos+68,10);# No Agents.
$f7 = substr($work,$startpos+79,12);# Coord. Node
$f8 = substr($work,$startpos+92,15);# Coord PID/Thread
if (length($work) >= $startpos+108) {
$f9 = substr($work,$startpos+108,30)}# Status
else {$f9 = "n/a" }
if (length($work) >= $startpos+139) {
$fa = substr($work,$startpos+139,26)}# Status Change
else {$fa = "n/a" }
if (length($work) >= $startpos+166) {
$fb = substr($work,$startpos+166,8)}# DBNAME
else {$fb = "n/a" }
if (length($work) >= $startpos+175) {
$fc = substr($work,$startpos+175)}# DB Path
else {$fc = "n/a" }
}
#print length($work)."$f1 $f2 $f3\n";
################################################################
# Wenn Ausgabedaten lokalisiert werden konnten
################################################################
if ($f_found) {
#print "eingetragen\n";
$t++;
$t_authid{$t} = $f1;# Auth ID
$t_applname{$t} = $f2;# Application Name
$t_id{$t} = xmpPerl::trim($f3);# Thread ID
$t_applid{$t} = $f4;# Application ID
$t_seq{$t} = $f5;# Sequence
$t_agentno{$t}= $f6;# Number of Agents
$t_node{$t} = $f7;# Coordinator Node
$t_pid{$t} = $f8;# Coordinator PID
$t_status{$t} = $f9;# Status
$t_statchgtm{$t}= $fa;# Status Change Time
$t_dbname{$t} = xmpPerl::trim($fb);# Database Name
$t_path{$t} = $fc;# DB Path
}
################################################################
# Jetzt gehts mit echten Daten los
################################################################
if ($f1 eq "--------") {
$f_found = 1;
}
}
}
################################################################################
# Liste der Threads fomattiert ausgeben
################################################################################
sub ReportThreads {
my $work;
my $work2;
$FORMAT_NAME = "ZEILE"; # $~
$FORMAT_TOP_NAME = "KOPF";# $^
$FORMAT_FORMFEED= "";# $^L
$FORMAT_LINES_PER_PAGE= ($t*8)+3;# $=, plus Lines für Kopf
$FORMAT_LINES_LEFT = 0;# vorhergeh. Format
$work = $t;
for ($t = 1; $t<=$work ; $t++) {
$f1 =$t_authid{$t};# Auth ID
$f2 =$t_applname{$t};# Application Name
$f3 =$t_id{$t};# Thread ID
$f4 =$t_applid{$t};# Application ID
$f5 =$t_seq{$t};# Sequence
$f6 =$t_agentno{$t};# Number of Agents
$f7 =$t_node{$t};# Coordinator Node
$f8 =$t_pid{$t};# Coordinator PID
$f9 =$t_status{$t};# Status
$fa =$t_statchgtm{$t};# Status Change Time
$fb =xmpPerl::trim($t_dbname{$t});# Database Name
$fc =$t_path{$t};# DB Path
if ( ($opt_d eq "*")
or ($opt_d eq $fb) ) {
write
}
}
}
################################################################################
# Eine oder alle Datenbanken deaktivieren
################################################################################
sub DeactivateDatabase {
my $work;
my $work2;
########################################################################
# Ausgesuchte Database oder alle?
########################################################################
if ($opt_d ne "*") {
$work = xmpPerl::doCmdOut("db2 deactivate db $opt_d");
#print "YYYYYY $work\n";
print "Database deactivated ........: ";
if (($work =~ 'DB20000I') or
($work =~ 'SQL1496W') or
($work =~ 'DB21024I') ) {
print "$opt_d successful\n";
}
else {
print "$opt_d unsuccessful\n";
print "$work\n";
}
}
else {
################################################################
# Alle Databases des Directories
################################################################
$work = $db;
for ($db = 1; $db <= $work; $db++) {
########################################################
# Local database?
########################################################
if ($dbtype{$db} eq "indirect") {
$work2 = xmpPerl::doCmdOut("db2 deactivate db $dbname{$db}");
#print "ZZZZZZZ $work\n";
print "Database deactivated ........: ";
if (($work2 =~ 'DB20000I') or
($work2 =~ 'SQL1496W') or
($work2 =~ 'DB21024I') ) {
print "$dbname{$db} successful\n";
}
else {
print "$dbname{$db} unsuccessful\n";
print "$work2\n";
}
}
else {
print "Database not deactivated ....: ".$dbname{$db}." is not local\n";
}
}
}
}
################################################################################
# Force Distinct Thread
################################################################################
sub ForceThread {
my $work;
my $work2;
$work2 = "db2 force application '(' ".$_[0]." ')'";
#print "FFFFFFF $work2\n";
$work = xmpPerl::doCmdOut($work2);
#print "GGGGGG $work\n";
print "Thread ID=".$_[0]." terminated ....: ";
if (($work =~ 'DB20000I') or
($work =~ 'DB21024I') ) {
print "successful\n";
}
else {
print "unsuccessful\n";
print "$work\n";
}
}
© Gernot Ruban