Translate

mardi 13 décembre 2016

LAST APPLIED / LAST RECEIVED - DataGuard

SET LINESIZE 2000
COL TIME FORMAT A20
COL NAME FORMAT A90
SELECT 'LAST APPLIED  : ' LOGS, TO_CHAR(NEXT_TIME,'DD-MON-YYYY HH24:MI:SS') TIME, SEQUENCE#, INCARNATION#, NAME
  FROM ( SELECT DISTINCT INC_B.INCARNATION#,
                FIRST_VALUE(ARC.NEXT_TIME) OVER (ORDER BY ARC.SEQUENCE# DESC) NEXT_TIME,
                FIRST_VALUE(ARC.SEQUENCE#) OVER (ORDER BY ARC.SEQUENCE# DESC) SEQUENCE#,
                FIRST_VALUE(ARC.NAME     ) OVER (ORDER BY ARC.SEQUENCE# DESC) NAME
           FROM V$DATABASE_INCARNATION INC_B, V$ARCHIVED_LOG ARC
          WHERE ARC.APPLIED = 'YES' AND
                ARC.RESETLOGS_CHANGE# = INC_B.RESETLOGS_CHANGE# AND ARC.RESETLOGS_TIME = INC_B.RESETLOGS_TIME AND
                INC_B.INCARNATION# = ( SELECT (CASE DBS.DATABASE_ROLE
                                                 WHEN 'SNAPSHOT STANDBY' THEN INC_A.PRIOR_INCARNATION#
                                                 ELSE INC_A.INCARNATION# END ) INCARNATION
                                         FROM V$DATABASE DBS, V$DATABASE_INCARNATION INC_A
                                        WHERE INC_A.STATUS ='CURRENT' ) )
UNION
SELECT 'LAST RECEIVED : ' LOGS, TO_CHAR(NEXT_TIME,'DD-MON-YYYY HH24:MI:SS') TIME, SEQUENCE#, INCARNATION#, NAME
  FROM ( SELECT DISTINCT INC_B.INCARNATION#,
                FIRST_VALUE(ARC.NEXT_TIME) OVER (ORDER BY ARC.SEQUENCE# DESC) NEXT_TIME,
                FIRST_VALUE(ARC.SEQUENCE#) OVER (ORDER BY ARC.SEQUENCE# DESC) SEQUENCE#,
                FIRST_VALUE(ARC.NAME     ) OVER (ORDER BY ARC.SEQUENCE# DESC) NAME
           FROM V$DATABASE_INCARNATION INC_B, V$ARCHIVED_LOG ARC
          WHERE ARC.RESETLOGS_CHANGE# = INC_B.RESETLOGS_CHANGE# AND ARC.RESETLOGS_TIME = INC_B.RESETLOGS_TIME AND
                INC_B.INCARNATION# = ( SELECT (CASE DBS.DATABASE_ROLE
                                                 WHEN 'SNAPSHOT STANDBY' THEN INC_A.PRIOR_INCARNATION#
                                                 ELSE INC_A.INCARNATION# END ) INCARNATION
                                         FROM V$DATABASE DBS, V$DATABASE_INCARNATION INC_A
                                        WHERE INC_A.STATUS ='CURRENT' ) ) ;

vendredi 13 mai 2016

ORA-15036: disk XXX is truncated



Chez un client et lors la mise à niveau du grid 11.2.0.3 vers 12.1.0.2 on a eu ce message d'erreur et on a "perdu" un de nos Diskgroups:

SQL> alter diskgroup ARCHMABD MOUNT FORCE ;
alter diskgroup ARCHMABD MOUNT FORCE
*
ERROR at line 1:
ORA-15032: not all alterations performed
ORA-15036: disk '/dev/rdsk/c0d35s0' is truncated



############################
### INF AVANT UPGRADE :  ###
############################
ASMCMD> lsdsk -k
Total_MB  Free_MB   OS_MB  Name                Failgroup           Failgroup_Type  Library  Label  UDID  Product  Redund   Path
1023952   120983  1023952  ARCHMABD_0000       ARCHMABD_0000       REGULAR         System                         UNKNOWN  /dev/rdsk/c0d28s0
1048576   123953  1048576  ARCHMABD_0001       ARCHMABD_0001       REGULAR         System                         UNKNOWN  /dev/rdsk/c0d35s0
1023952   121011  1023952  ARCHMABD_0002       ARCHMABD_0002       REGULAR         System                         UNKNOWN  /dev/rdsk/c0d61s0
1023952   121117  1023952  ARCHMABD_0003       ARCHMABD_0003       REGULAR         System                         UNKNOWN  /dev/rdsk/c0d62s0

Note : 
La taille des disques est déjà différente pour "/dev/rdsk/c0d35s0"

Comme le disque n'est pas monté il ne va pas apparaître :

ASMCMD> lsdsk -k -G ARCHMABD
Total_MB  Free_MB    OS_MB  Name  Failgroup  Failgroup_Type  Library  Label  UDID  Product  Redund   Path

Avec "sqlplus / as sysasm" : 

SET LINESIZE 2000
SELECT GROUP_NUMBER, NAME, SECTOR_SIZE, BLOCK_SIZE, STATE FROM V$ASM_DISKGROUP WHERE NAME LIKE 'ARCHMABD' ;
GROUP_NUMBER NAME                           SECTOR_SIZE BLOCK_SIZE STATE
------------ ------------------------------ ----------- ---------- -----------
  0 ARCHMABD                               0          0 DISMOUNTED


Correction  :

$  kfed read /dev/rdsk/c0d35s0 | egrep "name|size"

kfdhdb.dskname:           ARCHMABD_0001 ; 0x028: length=15
kfdhdb.grpname:                ARCHMABD ; 0x048: length=10
kfdhdb.fgname:            ARCHMABD_0001 ; 0x068: length=15
kfdhdb.capname:                         ; 0x088: length=0
kfdhdb.secsize:                     512 ; 0x0b8: 0x0200
kfdhdb.blksize:                    4096 ; 0x0ba: 0x1000
kfdhdb.ausize:                  1048576 ; 0x0bc: 0x00100000
kfdhdb.dsksize:                 1048576 ; 0x0c4: 0x00100000 ...(A)


Créer un fichier avec la métadonnée du disque :

$ kfed read /dev/rdsk/c0d35s0 > /tmp/header_d35s0.kfed
$ less /tmp/header_d35s0.kfed | grep "dsksize"
kfdhdb.dsksize:                 1048576 ; 0x0c4: 0x00100000


Comparer avec la taille de l'OS ( Décimal et hexadécimal ) , servez-vous de la calculatrice en mode programmeur si vous voulez.

$ /usr/sbin/devinfo -p /dev/rdsk/c0d35s0

/dev/rdsk/c0d35s0       76      3b0     2048    2147299328   0   4

2147299328 * 512 / 1024 / 1024 = 1048486...(B)
Dans ce cas 512 c'est le blocksize de l'OS
S'il y une différence entre (A) et (B) ...


Modifier le fichier header_d35s0.kfed et insérer la bonne taille du disque selon l'OS, sauvegardez les modifications : 
...
kfdhdb.dsksize:                 1048486 ; 0x0c4: 0x000FFFA6
...


Charger la métadonnée dans le disque :

$ kfed merge /dev/rdsk/c0d35s0 text=/tmp/header_d35s0.kfed_ok


Essayez de monter le diskgroup : 

SQL> ALTER DISKGROUP ARCHMABD MOUNT ;
Diskgroup altered.


On peut maintenant regarder le contenu : 

ASMCMD> cd ARCHMABD/
ASMCMD> ls
2015_08_10/
2015_08_11/
2015_08_12/
2015_08_13/



samedi 7 mai 2016

Kerberos - Oracle (Serveur) 11g


Pour être capable d'utiliser Kerberos avec une base de données Oracle :
La configuration a été faite sur un serveur Linuz mais sur Solaris c'est la même chose.

Identifier le nom du serveur de base de données :

oracle@donsuxx:/home/oracle> cat /etc/hosts
127.0.0.1       localhost
10.103.yy.xxx   donsuxx.domain.intra donsuxx


Créer les comptes dans l’AD selon l’exemple ci-dessous

      Compte de type « User », ce compte représente le nom du serveur :
    Name               : donsuxx
    Full name          : donsuxx.domain.intra
    User logon         : donsuxx
    Password           : Password!1
    Option             : Password never expire





      Compte de type « User », ce compte sert à renouveler les jetons :
    Name               : SVRENOUV
    Full name          : SVRENOUV
    User logon         : SVRENOUV
    Password           : Password!2
    Option             : User cannot change password et 
                         Password never expires





      Compte de type « User », ce compte est l’owner de la bd :
    Name               : ORACLE
    Full name          : ORACLE
    User logon         : ORACLE
    Password           : Password!3
    Option             : User cannot change password et 
                         Password never expires



Créer les comptes dans la bases de données 

·       Créer le compte «SVRENOUV »  sur le serveur de base de données avec le même mot de passe de l’AD.

DROP USER "SVRENOUV@DOMAIN.INTRA" CASCADE;
CREATE USER "SVRENOUV@DOMAIN.INTRA"
  IDENTIFIED EXTERNALLY
  DEFAULT TABLESPACE USERS
  TEMPORARY TABLESPACE TEMP
  PROFILE DEFAULT
  ACCOUNT UNLOCK;
  GRANT CREATE SESSION TO "SVRENOUV@DOMAIN.INTRA";

·       Le compte « ORACLE » qui existe déjà sur le serveur doit avoir aussi le même mot de passe que dans l’AD

DROP USER "ORACLE@DOMAIN.INTRA" CASCADE;
CREATE USER "ORACLE@DOMAIN.INTRA"
  IDENTIFIED EXTERNALLY
  DEFAULT TABLESPACE USERS
  TEMPORARY TABLESPACE TEMP
  PROFILE DEFAULT
  ACCOUNT UNLOCK;
  GRANT CREATE SESSION TO "ORACLE@DOMAIN.INTRA";

·        Dans l’AD, vérifier si de doublons existent sur le compte qu’on vient de créer (celle qui représente la machine).  En théorie il ne doit pas en avoir de doublons reliés à notre compte.
Commande : setspn –X

·        Dans l’AD, créer le keytab
ktpass -princ oraevta/donsuxx.domain.intra@DOMAIN.INTRA -crypto all -pass Password!1 -mapuser donsuxx@DOMAIN.INTRA -ptype KRB5_NT_PRINCIPAL -out C:\key\keytab

      Dans la commande il faut cibler :
o   Le nom du service « oraevta » est juste un nom à utiliser qui doit coïncider avec le nom spécifié dans le sqlnet.ora de la bd.
Il pourrait être par exemple : ora, ora11, etc.




o   Le paramètre « -pass » correspond au même mot de passe du compte qui représente la machine qu’on vient de créer.
o   Le paramètre « -mapuser » doit faire référence au même compte.

·        Envoyer le fichier « keytab » qu’on vient de créer vers le serveur de bd et le placer à l’endroit indiqué dans le « sqlnet.ora ».



·        Vérifier le nom du fichier tampon pour les jetons



·        Valider les privilèges sur les fichiers
-rw-rw---- 1 oracle oinstall 437 2016-04-22 09:37 keytab
-rwxrwx--- 1 oracle oinstall 692 2016-04-21 16:33 krb5.conf


·        Valider que les entrés dans le fichier services soient comme ça :

oracle@donsuxx:> cat /etc/services | grep kerberos
     kerberos         88/tcp    kerberos5 krb5    # Kerberos
     kerberos         88/udp    kerberos5 krb5    # Kerberos
     kerberos-adm    749/tcp    # kerberos administration
     kerberos-adm    749/udp    # kerberos administration
     kerberos-iv     750/udp    kerberos4 kerberos-sec kdc    # kerberos version iv
     kerberos-iv     750/tcp    kerberos4 kerberos-sec kdc
     kerberos_master 751/udp    # Kerberos authentication
     kerberos_master 751/tcp    # Kerberos authentication


·        Sur le serveur de BD, détruire les jetons existants, le nom du fichier .RC sera en fonction du nom du service.
okdstry -c /tmp/tmpevta
rm /tmp/oraevta.RC

·        Sur le serveur de BD, Initialiser les jetons, fournir le mot de passe demandé.

okinit -c /tmp/tmpevta -e 23 SRV_RENOUV
 ou selon le chiffrement 
okinit -c /tmp/tmpevta -e 1 -e 3 oracle      

     Exemple :
oracle@donsuxx:/home/oracle> okinit -c /tmp/tmpevta -e 23 SVRENOUV

Kerberos Utilities for Linux: Version 11.2.0.4.0 - Production on 22-APR-2016 10:02:30

Copyright (c) 1996, 2013 Oracle.  All rights reserved.

Password for SVRENOUV@DOMAIN.INTRA:


·        Sur le serveur de BD, lister les jetons

oklist

oracle@donsuxx:/home/oracle>  oklist

Kerberos Utilities for Linux: Version 11.2.0.4.0 - Production on 22-APR-2016 11:28:16

Copyright (c) 1996, 2013 Oracle.  All rights reserved.

Ticket cache: /tmp/tmpevta
Default principal: SVRENOUV@DOMAIN.INTRA

   Valid Starting           Expires            Principal
22-Apr-2016 10:04:08  22-Apr-2016 18:02:30  krbtgt/DOMAIN.INTRA@DOMAIN.INTRA

·        Sur le serveur de BD, tester la connexion kerberos. Il faut noter que la connexion est faite avec le même utilisateur qui a fait le renouvellement

sqlplus /@MABD


oracle@donsuxx:~> sqlplus /@MABD

SQL*Plus: Release 11.2.0.4.0 Production on Fri Apr 22 11:29:03 2016

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> show user
USER is "SVRENOUV@DOMAIN.INTRA"



Note:  Si vous voulez tester la connexion sur une base de données StandBy, elle doit être en Snapshot et non pas en Physical pour que la connexion se fasse.



Le Client Windows 2008 R2 

           Exemple de "sqlnet.ora"

# sqlnet.ora Network Configuration File: C:\oracle\product\10.2.0\client_1\NETWORK\ADMIN
# Generated by Oracle configuration tools.

NAMES.DEFAULT_DOMAIN = votredomain.ca

################################################################
# Methodes Authentifications utilises sont TCPS and Kerberos5
################################################################
NAMES.DIRECTORY_PATH=(TNSNAMES)
SQLNET.AUTHENTICATION_SERVICES=(BEQ,KERBEROS5)

################################################################
# Ajoute pour la configuration Kerberos 5 -
################################################################
SQLNET.KERBEROS5_CONF=C:\Logiciels\oracle\ora1120\kerberos\krb5.conf
SQLNET.KERBEROS5_CONF_MIT=true
SQLNET.KERBEROS5_CC_NAME = OSMSFT://
SQLNET.AUTHENTICATION_KERBEROS5_SERVICE=ora
SQLNET.EXPIRE_TIME=0



Le Client Windows 2012 R2 

           Exemple de "sqlnet.ora"

# sqlnet.ora Network Configuration File: C:\oracle\product\10.2.0\client_1\NETWORK\ADMIN
# Generated by Oracle configuration tools.

NAMES.DEFAULT_DOMAIN = votredomain.ca

################################################################
# Methodes Authentifications utilises sont TCPS and Kerberos5
################################################################
NAMES.DIRECTORY_PATH=(TNSNAMES)
SQLNET.AUTHENTICATION_SERVICES=(NTS)

################################################################
# Ajoute pour la configuration Kerberos 5 -
################################################################
SQLNET.KERBEROS5_CONF=C:\Logiciels\oracle\ora1120\kerberos\krb5.conf
SQLNET.KERBEROS5_CONF_MIT=true
SQLNET.KERBEROS5_CC_NAME = OSMSFT://
SQLNET.AUTHENTICATION_KERBEROS5_SERVICE=ora
SQLNET.EXPIRE_TIME=0












samedi 2 avril 2016

Tracer une session bd avec truss - Option II -

Des fois un trace de base de données ne suffit pas pour retrouver un problème. Dans ce cas, je vais activer aussi un trace au niveau du système d'exploitation avec la commande truss.

##############################################
### Option II   ##############################
##############################################

Système d'exploitation :  Solaris 10
Version de base de données : 11.2.0.4

  • Créer le fichier shell :

Fichier shell : bd_truss.sh
#!/bin/sh
/usr/bin/nohup /usr/bin/truss -fldD -p $2 > /home/ora11204/$1 2>&1&

Cela va générer un fichier de trace qui sera placé dans le répertoire "/home/ora11204/" , Le nom du fichier est passé comme 1er paramètre , le 2ème paramètre correspond au "ID process".


  • Demander à votre admin Unix de donner les privilèges SUID pour le truss, en cas l'owner de votre process à tracer ne soit pas le même.(Exemple : grid et home RDBMS installés avec des comptes séparés).

root@serveur:/root# ls -l /usr/bin/truss
-r-xr-xr-x  66 root     bin        10052 Jul  6  2011 /usr/bin/truss

root@serveur:/root# chmod u+s /usr/bin/truss

root@serveur:/root# ls -l /usr/bin/truss
-r-sr-xr-x  66 root     bin        10052 Jul  6  2011 /usr/bin/truss


  • Créer un compte de test dans la base de données :

sqlplus / as sysdba
DROP USER EVTA CASCADE ;
CREATE USER EVTA IDENTIFIED BY EVTA  ;
GRANT CONNECT, RESOURCE TO EVTA ;

  • Créer la crédentiale -Puisque c'est 11gR2-

EXEC DBMS_SCHEDULER.CREATE_CREDENTIAL('CRED_EVTA','ora11204','yourpasswordunix') ;


  • Utiliser le trigger pour créer une "job"

CREATE OR REPLACE TRIGGER SYS.TRIG_TRACE_JOB
AFTER LOGON ON DATABASE
DISABLE
DECLARE
id1             VARCHAR2(30);
id2             NUMBER;
ls_username     VARCHAR2(30);
ls_osuser       VARCHAR2(30);
ls_program      VARCHAR2(64);
ls_sid          INTEGER;
ls_serial       INTEGER;
ls_schemaname   VARCHAR2(100);
ls_machine      VARCHAR2(100);
ls_spid         VARCHAR2(24);
v2              NUMBER;
result          NUMBER;

CURSOR USAGERINFO IS
   SELECT upper(A.username), A.osuser, upper(A.program), A.sid, A.serial#, A.schemaname, A.machine, B.SPID
     FROM v$session A, v$process b
    WHERE audsid = userenv('SESSIONID') and a.paddr=b.addr;
BEGIN
    -- Obtenir les informations de l'usager en cours
    OPEN USAGERINFO;
       FETCH USAGERINFO
       INTO ls_username, ls_osuser, ls_program, ls_sid, ls_serial, ls_schemaname, ls_machine, ls_spid;
       CLOSE USAGERINFO;

    if user in ('EVTA') and program like 'SQLPLUS%' then
      select user, sys_context('USERENV','SID') into id1, id2 from dual;
      execute immediate 'alter session set statistics_level=ALL';
      execute immediate 'alter session set tracefile_identifier='''||replace(id1,'$','')||'_'||id2||'''';
      execute immediate 'alter session set max_dump_file_size=40960000';
      execute immediate 'alter session set EVENTS ''10046 trace name context forever, level 12''';
      execute immediate 'BEGIN DBMS_SCHEDULER.CREATE_JOB(JOB_NAME=>'''||'JOB_EVTA'||id2||''''||',JOB_TYPE=>'||'''EXECUTABLE'''||',JOB_ACTION=>'||''''||'/home/ora11204/bd_truss.sh'||''''||',NUMBER_OF_ARGUMENTS=>2,ENABLED=>FALSE,AUTO_DROP=>TRUE,CREDENTIAL_NAME=>'||''''||'CRED_EVTA'||'''); END;' ;
      execute immediate 'BEGIN DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE('''||'JOB_EVTA'||id2||''''||',1,'||''''||'trace_'||ls_spid||''''||'); END;';
      execute immediate 'BEGIN DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE('''||'JOB_EVTA'||id2||''''||',2,'||''''||ls_spid||''''||'); END;';
      execute immediate 'BEGIN DBMS_SCHEDULER.ENABLE('''||'JOB_EVTA'||id2||''''||') ; END;';
    end if;
END;
/


  • Activer le trigger au moment dont vous aurez besoin


ALTER TRIGGER SYS.TRIG_TRACE_JOB ENABLE ; 

Cela va activer deux types de traces à chaque connexion du compte "EVTA", un trace de bases de données et un trace OS, ces deux fichiers pourront vous aider à détecter certains problèmes.

vendredi 1 avril 2016

Tracer une session bd avec truss - Option I -

Des fois un trace de base de données ne suffit pas pour retrouver un problème. Dans ce cas, je vais activer aussi un trace au niveau du système d'exploitation avec la commande truss.

##############################################
### Option I   ###############################
##############################################

Système d'exploitation :  Solaris 10
Version de base de données : 11.2.0.4

  • Créer le fichier shell :

Fichier shell : bd_truss.sh
#!/bin/sh
/usr/bin/nohup /usr/bin/truss -fldD -p $2 > /home/ora11204/$1 2>&1&

Cela va générer un fichier de trace qui sera placé dans le répertoire "/home/ora11204/" , Le nom du fichier est passé comme 1er paramètre , le 2ème paramètre correspond au "ID process".


  • Demander à votre admin Unix de donner les privilèges SUID pour le truss, en cas l'owner de votre process à tracer ne soit pas le même.(Exemple : grid et home RDBMS installés avec des comptes séparés).

root@serveur:/root# ls -l /usr/bin/truss
-r-xr-xr-x  66 root     bin        10052 Jul  6  2011 /usr/bin/truss

root@serveur:/root# chmod u+s /usr/bin/truss

root@serveur:/root# ls -l /usr/bin/truss
-r-sr-xr-x  66 root     bin        10052 Jul  6  2011 /usr/bin/truss


  • Créer un compte de test dans la base de données :

sqlplus / as sysdba
DROP USER EVTA CASCADE ;
CREATE USER EVTA IDENTIFIED BY EVTA  ;
GRANT CONNECT, RESOURCE TO EVTA ;


  • Octroyer les privilèges nécessaires

execute dbms_java.grant_permission( 'EVTA', 'SYS:java.io.FilePermission', '/usr/bin/truss', 'execute' );
execute dbms_java.grant_permission( 'EVTA', 'SYS:java.io.FilePermission', '/usr/bin/sh', 'execute' );
execute dbms_java.grant_permission( 'EVTA', 'SYS:java.io.FilePermission', '/home/ora11204/bd_truss.sh', 'execute' );
execute dbms_java.grant_permission( 'EVTA', 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '' );
execute dbms_java.grant_permission( 'EVTA', 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '' );

ALTER SESSION SET CURRENT_SCHEMA=EVTA ;

Note: Ces deux classes ont été obtenues du Site d'Oracle - Doc ID 109095.1


  • Créer les classes Java


CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "CaptureStream" AS
import java.util.*;
import java.io.*;
class CaptureStream implements Runnable {
    private final InputStream is;
    private final String type;
    private final OutputStream redirect;
    private boolean  redirected = false;

    CaptureStream(InputStream is, String type, OutputStream redirect)
    {
        this.is = is;
        this.type = type + ">";
        this.redirect = redirect;
    }

    CaptureStream(InputStream is, String type)
    {
        this(is, type, null);
    }

    CaptureStream(InputStream is)
    {
        this(is, " ", null);
    }

    public void run()
    {
        try {
            PrintWriter pw = null;
            if (redirect != null) {
                pw = new PrintWriter(redirect);
                redirected = true;
            }

            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null) {
                System.out.println(type + line);   
                if (redirected) {
                    pw.println(line);
                }
            }
            if (redirected) {
                pw.flush();
                pw.close();
            }
            br.close();
            isr.close();
        } catch (IOException ioe) {
            ioe.printStackTrace(); 
        }
    }
}
/


CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "ExecOSCmd" AS
import java.util.*;
import java.io.*;
public class ExecOSCmd {
    public static void main (String args[])
    {
        int rc = 0;
        if (args.length < 1) {
            System.out.println("USAGE: java ExecOSCmd \'cmd\' ");
            System.exit(1);
        }

        try {
            String cmd = args[0];
            FileOutputStream fos = null;
            if (args.length == 2 ) {
                fos = new FileOutputStream(args[1]);
            }
            Runtime rt = Runtime.getRuntime();
            Process p = rt.exec(cmd);


            CaptureStream err = new CaptureStream(p.getErrorStream(), "ERR");           
            Thread e = new Thread(err);

            /* NOTE we do not join the error thread.  If there was no
         Error it may never return.  We would wait forever for it to
         return thus janging this process */
            e.start();

            CaptureStream out = new CaptureStream(p.getInputStream(),
                                                  "OUT", fos);
            Thread o = new Thread(out);
            o.start();

            try {
                rc = p.waitFor();
                /* Handle exceptions for waitFor() */
            } catch (InterruptedException intexc) {
                System.out.println("Interrupted Exception on waitFor: " +
                                   intexc.getMessage());
            }

            if (fos !=null) {
                o.join();      // need to wait for the output to finish.
                fos.flush();
                fos.close();
            }

            System.out.println("ExitValue: " + rc);

        } catch (Throwable t) {
            System.out.println("ExitValue: " + rc);
            t.printStackTrace();
        }
    }
}
/

CREATE OR REPLACE PROCEDURE executecmd (cmd VARCHAR2)
AS LANGUAGE JAVA NAME 'ExecOSCmd.main(java.lang.String[])';
/

En tant que sys :

SET LINESIZE 2000
SELECT OBJECT_TYPE, OBJECT_NAME FROM DBA_OBJECTS WHERE OWNER = 'EVTA';
    OBJECT_TYPE         OBJECT_NAME
    ------------------- ---------------------------------------
    JAVA CLASS          CaptureStream
    JAVA SOURCE         CaptureStream
    JAVA CLASS          ExecOSCmd
    JAVA SOURCE         ExecOSCmd
    PROCEDURE           EXECUTECMD

SET LINESIZE 600
COL TYPE_NAME   FORMAT A30
COL NAME        FORMAT A30
COL ACTION      FORMAT A30
SELECT * FROM DBA_JAVA_POLICY WHERE GRANTEE = 'EVTA';
    KIND   GRANTEE   TYPE_SCHEMA TYPE_NAME                      NAME                           ACTION     ENABLED  SEQ
    ------ --------- ----------- ------------------------------ ------------------------------ ---------- -------- ---
    GRANT  EVTA      SYS         java.io.FilePermission         /home/ora11204/bd_truss.sh     execute    ENABLED  193
    GRANT  EVTA      SYS         java.io.FilePermission         /usr/bin/sh                    execute    ENABLED  192
    GRANT  EVTA      SYS         java.io.FilePermission         /usr/bin/truss                 execute    ENABLED  191
    GRANT  EVTA      SYS         java.lang.RuntimePermission    readFileDescriptor                        ENABLED  195
    GRANT  EVTA      SYS         java.lang.RuntimePermission    writeFileDescriptor                       ENABLED  194


  • Créer un trigger after logon
La ligne importante est la dernière, le "execute immediate" appelle la procédure "executecmd" qui à travers la classe Java va déclencher le script "bd_truss.sh", lequel à la fois, va exécuter le "truss" pour le processus OS qui est en train de s'ouvrir.

CREATE OR REPLACE TRIGGER SYS.TRIG_TRACE_JAVA
AFTER LOGON ON DATABASE
DISABLE
DECLARE
id1             VARCHAR2(30);
id2             NUMBER;
ls_username     VARCHAR2(30);
ls_osuser       VARCHAR2(30);
ls_program      VARCHAR2(64);
ls_sid          INTEGER;
ls_serial       INTEGER;
ls_schemaname   VARCHAR2(100);
ls_machine      VARCHAR2(100);
ls_spid         VARCHAR2(24);
v2              NUMBER;
result          NUMBER;

CURSOR USAGERINFO IS
   SELECT upper(A.username), A.osuser, upper(A.program), A.sid, A.serial#, A.schemaname, A.machine, B.SPID
     FROM v$session A, v$process b
    WHERE audsid = userenv('SESSIONID') and a.paddr=b.addr;
BEGIN
    -- Obtenir les informations de l'usager en cours
    OPEN USAGERINFO;
       FETCH USAGERINFO
       INTO ls_username, ls_osuser, ls_program, ls_sid, ls_serial, ls_schemaname, ls_machine, ls_spid;
       CLOSE USAGERINFO;

    if user in ('EVTA') then
      select user, sys_context('USERENV','SID') into id1, id2 from dual;
      execute immediate 'alter session set statistics_level=ALL';
      execute immediate 'alter session set tracefile_identifier='''||replace(id1,'$','')||'_'||id2||'''';
      execute immediate 'alter session set max_dump_file_size=40960000';
      execute immediate 'alter session set EVENTS ''10046 trace name context forever, level 12''';
      execute immediate 'BEGIN EVTA.executecmd('''||'/home/ora11204/bd_truss.sh trace_'||replace(id1,'$','')||'_'||id2||'_'||ls_spid||'.txt '||ls_spid||'''); END;' ;
    end if;
END;
/

  • Activer le trigger au moment dont vous aurez besoin


ALTER TRIGGER SYS.TRIG_TRACE_xxx ENABLE ; 

Cela va activer deux types de traces à chaque connexion du compte "EVTA", un trace de bases de données et un trace OS  , ces deux fichiers pourront vous aider à détecter certains problèmes.