Est-il possible de lancer un shell UNIX (ou une commande système) à partir d'une procédure stockée?
Je suis en Oracle 8.1.7 sous SUN Solaris
Version imprimable
Est-il possible de lancer un shell UNIX (ou une commande système) à partir d'une procédure stockée?
Je suis en Oracle 8.1.7 sous SUN Solaris
Pour exécuter une commande système depuis du PL/SQL nous allons utiliser une classe Java. La création d'un classe java exécutable en PL/SQL passe par trois étapes : tout d'abord on créé la Java Source, ensuite on publie la spécification d'appel de cette source et enfin on accorde les privilèges nécessaires à l'exécution de cette classe Java.
Donc on va tout d'abord créer la classe Java permettant d'exécuter une commande système:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "Host" AS import java.io.*; public class Host { public static void executeCommand(String command) { try { String[] finalCommand; if (isWindows()) { finalCommand = new String[4]; finalCommand[0] = "C:\\windows\\system32\\cmd.exe"; finalCommand[1] = "/y"; finalCommand[2] = "/c"; finalCommand[3] = command; } else { finalCommand = new String[3]; finalCommand[0] = "/bin/sh"; finalCommand[1] = "-c"; finalCommand[2] = command; } final Process pr = Runtime.getRuntime().exec(finalCommand); new Thread(new Runnable() { public void run() { try { BufferedReader br_in = new BufferedReader(new InputStreamReader(pr.getInputStream())); String buff = null; while ((buff = br_in.readLine()) != null) { System.out.println("Process out :" + buff); try {Thread.sleep(100); } catch(Exception e) {} } br_in.close(); } catch (IOException ioe) { System.out.println("Exception caught printing process output."); ioe.printStackTrace(); } } }).start(); new Thread(new Runnable() { public void run() { try { BufferedReader br_err = new BufferedReader(new InputStreamReader(pr.getErrorStream())); String buff = null; while ((buff = br_err.readLine()) != null) { System.out.println("Process err :" + buff); try {Thread.sleep(100); } catch(Exception e) {} } br_err.close(); } catch (IOException ioe) { System.out.println("Exception caught printing process error."); ioe.printStackTrace(); } } }).start(); } catch (Exception ex) { System.out.println(ex.getLocalizedMessage()); } } public static boolean isWindows() { if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) return true; else return false; } }; / show errors java source "Host"
Ensuite on publie la spécification d'appel de cette classe en utilisant une procédure PL/SQL pour la "wrapper":
Code:
1
2
3
4 CREATE OR REPLACE PROCEDURE Host_Command (p_command IN VARCHAR2) AS LANGUAGE JAVA NAME 'Host.executeCommand (java.lang.String)'; /
Enfin, les permissions nécessaire doivent être données par l'utilisateur SYS pour que le JServer puisse accèder aux fichiers su système:
On doit se reconnecter pour activer les privilèges.Code:
1
2
3
4
5 EXEC Dbms_Java.Grant_Permission('SCHEMA-NAME', 'java.io.FilePermission', '<>', 'read ,write, execute, delete'); EXEC Dbms_Java.Grant_Permission('SCHEMA-NAME', 'SYS:java.lang.RuntimePermission', 'writeFileDescriptor', ''); EXEC Dbms_Java.Grant_Permission('SCHEMA-NAME', 'SYS:java.lang.RuntimePermission', 'readFileDescriptor', '');
Ensuite on lance notre commande
Code:
1
2
3
4
5
6 SET SERVEROUTPUT ON SIZE 1000000 CALL DBMS_JAVA.SET_OUTPUT(1000000); BEGIN Host_Command (p_command => 'move C:\test1.txt C:\test2.txt'); END; /
Lors du lancement de la première commande CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "Host" AS....., j'obtiens le message suivant :
ERROR at line 1:
ORA-29547: Java system class not available: oracle/aurora/rdbms/Compiler
Je suppose que je dois faire quelque chose pour pouvoir utiliser cette commande, je ne sais malheureusemebt pas quoi....
arg je crois que tu as pas du installer le support java. Je vais voir si je trouve plus d'info
pour installer la jvm oracle, tu dois executer le fichier initjvm.sql
qui se trouve sous :
$ORACLE_HOME\javavm\install\initjvm.sql
tu risues d'avoir des souci avec les aprametre java pool du fichier init.ora.
Si c le cad augmente les...en esperant que tu es assez de RAM..car la JVM est assez gurmande.
Bon courage
ps : initjvm.sql doit etre lance sous SYS
Effectivemment, j'ai eu quelques problèmes de java_pool_size, large_pool_size, shared_pool_size.
J'ai pris les valeurs suivantes :
java_pool_size = 50M
large_pool_size = 45M
shared_pool_size=70M
J'ai ensuite positionner le LD_LIBRARY_PATH64 sur $ORACLE_HOME/lib64 dans l'environnement UNIX.
Petite explication dans la procédure de grant :
EXEC Dbms_Java.Grant_Permission('SCHEMA-NAME', 'java.io.FilePermission', '<>', 'read ,write, execute, delete');
le '<>' doit être remplacer par le répertoire dans lequel se trouve le shell ou la commande (exemple bin/sh pour la commande ls).
Ensuite tout roule...
Merci à tous
comment executer une commande système sous oracle si on n'a pas la jvm et que le dba ne peut l'installer ??
c'est pas possible :ange:
je dis à mon chef de projet que c'est pas possible ou c'est une blague ? 8O
Si, c'est possible :
http://www.developpez.net/forums/vie...highlight=host
es tu sur que je peux pas mettre ma commande sys. direct dans ma proc ?
car elle nécessite un paramètre qu'elle récupère dans le LOOP.
On peut pas faire un truc de ce style :
Code:
1
2
3
4 --envoi du mail via une commande système à destination de BLAT.EXE --ho blat fichier -t fctn_GetMailRecipient(LyceeNum) -f moi@domaine.fr -s \"Le sujet\";
pourquoi s'évertuer à ne pas utiliser utl_snmp ? :roll:
Citation:
Envoyé par plaineR
au temps pour moi :bravo:
Ca tu peux le faire puisque tout est en commentaires :aie:Citation:
Envoyé par c_moi_c_moi
Plus sérieusement, c'est quoi ton ho ?
on m'a dit que ca permettait d'exécuter une commande système dans une proc. stock., syntaxe de la sorte suivante :
ho commde systeme
A mon avis, c'est l'abréviation de la commande host de SQL*Plus.
:arrow: ne fonctionne pas dans une procédure stockée.
où dois je donc lancer ma commande sql*plus ?
Sous SQL*Plus, non ?
STOP AU SQUAT DE SUJET !!!!
c_moi_c_moi :arrow: continue dans TON sujet !
:mouarf1: Bonjour aux connaisseurs, :oops:
je voudrais sous Unix/Oracle pouvoir lancer un script Shell dans lequel figurerait des requêtes SQL du genre :
UPDATE UC10 SET TICONN = '0001-01-01-00.00.00'
DELETE FROM CO22 WHERE CDUTIL IN ( SELECT CDUTIL FROM UC10 WHERE TYUTIL = 'A')
DELETE FROM UC10 WHERE TYUTIL = 'A'
Est-ce possible et comment faire ? :P
Merci de me donner les syntaxes de lancement des requêtes SQL en Shell.
:roll: