Seiten

Samstag, 22. Dezember 2012

dbms_scheduler mit EXECUTABLE unter Windows

Will man unter Windows datenbankgesteuert regelmäßig Dateioperationen im Netzwerk ausführen, muss man einige Hürden überwinden.
An diesem Beispiel beschreibe ich die notwendigen Schritte:
Aus der Oracledatenbank (11.2.0.3) wird täglich um 20:00Uhr eine Batchdatei (d:\skripte\backup.bat) gestartet, die eine Datei inkl. Tagesdatum ins Firmennetz sichern soll.

Der Inhalt der backup.bat:
set jahr=%date:~-4%
set monat=%date:~-7,2%
set tag=%date:~-10,2%

copy D:\oradata\orcl\backup.zip \\192.168.2.100\bckp\%jahr%%monat%%tag%_backup.zip
Das Skript um den Scheduler-Job zu erzeugen, sieht so aus:
BEGIN
  DBMS_SCHEDULER.CREATE_JOB(
    job_name         => 'JOB_COPY_BACKUP'
    ,repeat_interval => 'FREQ=DAILY;BYHOUR=20'
    ,job_class       => 'DEFAULT_JOB_CLASS'
    ,job_type        => 'EXECUTABLE'
    ,NUMBER_OF_ARGUMENTS => 2
    ,job_action      => 'c:\windows\system32\cmd.exe'
    ,comments        => 'Job startet das Backup.'
    );
END;
/
Das Grundgerüst steht damit. Weil man die Batchdatei nicht direkt aufrufen kann, muss man sie als Argument an die Commandshell inkl. Schalter "/C" übergeben. Das sähe dann in etwa so aus: "c:\windows\system32\cmd.exe /c d:\skripte\backup.bat > nul"
Diese Argumente setzt man mit DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(). Das Logging setzt man mit DBMS_SCHEDULER.SET_ATTRIBUTE. Diese Loglevel gibt es:
  • DBMS_SCHEDULER.LOGGING_OFF,
  • DBMS_SCHEDULER.LOGGING_RUNS,
  • DBMS_SCHEDULER.LOGGING_FULL
Wenn man AUTO_DROP auf FALSE setzt, verhindert man, dass der Job nach der letzten Ausführung aus der DB verschwindet.
Zuletzt muss der Job enabled werden. Standardmäßig sind die Jobs disabled und werden damit nicht ausgeführt.
BEGIN
  DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE('JOB_COPY_BACKUP',1,'/c');
  DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(
    'JOB_COPY_BACKUP',2,'d:\skripte\backup.bat > nul');
  DBMS_SCHEDULER.SET_ATTRIBUTE(
    name       => 'JOB_COPY_BACKUP'
    ,attribute => 'LOGGING_LEVEL'
    ,value     => DBMS_SCHEDULER.LOGGING_RUNS);
  DBMS_SCHEDULER.SET_ATTRIBUTE( 
    name       => 'JOB_COPY_BACKUP'
    ,attribute => 'AUTO_DROP'
    ,value     => FALSE);
  DBMS_SCHEDULER.ENABLE('JOB_COPY_BACKUP');
END;
/
Bei einem "normalen" Job ohne Netzwerkugriff wäre man jetzt fertig. In diesem Fall würde der Job in einer  Fehlermeldung enden.
Was ist zu beachten? Der Prozess, der die Batchdatei startet, muss unter einem Konto laufen, dass Schreibrechte ins Netz hat.
Nach einer Standardinstallation werden die Windowsdienste unter dem Systemkonto (Local System) ausgeführt. Der Schedulerservice selbst ist sogar disabled:
















Den Service muss man enablen und einem Konto zuweisen, das Schreibrechte ins Netzwerk besitzt - hier ora_dba:

Jetzt sollte der Job wie erwartet funktionieren. Das Log kann man mit diesem Select abrufen:
select * from dba_scheduler_job_log
where job_name = 'JOB_COPY_BACKUP'
Was gibt es sonst noch?
  • Man kann Jobs auch über "credentials" mit Username und Passwort starten. Das habe ich noch nicht ausprobiert.
  • Wenn man einen "EXECUTABLE-Job" in einer RAC-Umgebung anlegt, gibt es das Problem, dass der Scheduler-Job auf jedem Knoten ausgeführt werden kann. Dann muss man entweder dafür sorgen, dass die Files (Programme, Batch-Dateien...), auch tatsächlich für jeden Knoten auffindbar sind - Oder: Man sorgt dafür, dass der Scheduler-Job nur auf einem bestimmten Knoten läuft. Dazu später. (Stichwort: job_class)
  • Möchte man über Probleme oder auch nur die reine Jobausführung per Email benachrichtigt werden, kann man sich seit 11g bequem per eingebauter "email_notification" benachrichtigen lassen.
  • Außerdem bietet das Scheduler-Package auch die Möglichkeit, per Window die Ausführungszeiten zu steuern.

2 Kommentare:

  1. Hi Marco,

    I found very useful your article but I have doubt. To enable the service you have used the "ora_dba" account.
    How was that account created? Is the account to access your windows computer or the account in the database where the job must be executed?
    I have manually activated the job but always fails to execute. I have not established the account because I receive the error "the account name is not valid or does not exists....".

    Thanks in advance.

    AntwortenLöschen
  2. Hi,

    take a windowsaccount/systemaccount. Using a database user is the wrong solution.

    Best regards,
    Marco

    AntwortenLöschen