# opsi -script internal flow

### uib gmbh

## opsiscript Internal Flow

## Übersicht1

- Sequentiell
- Entscheidungen
  - if then else endif
  - switch

## Übersicht2

- Errordetection
  - exitcode
  - markErrorNumber / errorsOccurredSinceMark
- Reaktion auf Errors
  - LogError
  - isFatalError
  - isSuspended
  - do not run updatescript

## Übersicht3

CodeBlöcke

- sub Sektionen
  - externe Sub-Sektionen
- include
- setup / update
- lokale Funktionen

## Sequentiell

Standard: Zeile für Zeile

## Entscheidungen1

if / else / endif

Syntax:

    if <boolean expression>
      <statement(s)>
    [else
      <statement(s)>]
    endif

## Entscheidungen2

switch

Syntax:

    Switch <string expression>
      Case <string const>
        <statement(s)>
      EndCase
      [DefaultCase
        <statement(s)>
       EndCase]
    EndSwitch

Beispiel:

    switch $distrotype$
            case "redhat"
                    set $package_lock_file$ = '/var/run/yum.pid.'
            endcase
            case "suse"
                    set $package_lock_file$ = '/run/zypp.pid'
            endcase
            case "debian"
                    set $package_lock_file$ = '/var/lib/dpkg/lock'
            endcase
            DefaultCase
                    LogError "unknown Release"
            EndCase
    endswitch

## Errordetection

Methoden:

    getLastExitCode :string (exitcode) [W/L]
    shellCall (<command string>) :string (exitcode) [W/L]
    startProcess(<string>) :string (exitcode)  [W/L]

    markErrorNumber / errorsOccurredSinceMark [W/L]
    LogError

## Errordetection 1: Exitcode 1

Methoden:

    getLastExitCode :string (exitcode) [W/L]

- Die String-Funktion getLastExitCode gibt den ExitCode des letzten Prozessaufrufs der vorausgehenden WinBatch / DosBatch / ExecWith Sektion aus.
- Der Aufruf anderer opsi-winst Befehle ( wie z.B. einer Files Sektion) verändert den gefundenen ExitCode nicht.
- Bei DosBatch und ExecWith Sektionen erhalten wir den Exitcode des Interpreters. Daher muss in der Regel der gewünschte Exitcode in der Sektion explizit übergeben werden.

## Errordetection 1: Exitcode 2

(error_exitcode_0.opsiscript)

cmd.exe

    [ShellInAnIcon_win_exit1]
    rem create an errorlevel= 1
    echo huhu | findstr ha
    exit %ERRORLEVEL%

bash

    [ShellInAnIcon_lin_exit1]
    set -x
    # create an exit code= 1
    echo huhu | grep ha
    exit $?

## Errordetection 1: Exitcode 3

(error_exitcode_1.opsiscript)

cmd.exe

    [ShellInAnIcon_win_exit1]
    rem create an errorlevel= 1
    echo huhu | findstr ha
    rem create an errorlevel= 0
    echo huhu | findstr hu
    exit %ERRORLEVEL%

bash

    [ShellInAnIcon_lin_exit1]
    set -x
    # create an exit code= 1
    echo huhu | grep ha
    # create an exit code= 0
    echo huhu | grep hu
    exit $?

## Errordetection 1: Exitcode 3a

(error_exitcode_2.opsiscript)

cmd.exe

    [ShellInAnIcon_win_exit1]
    set exitcode=0
    rem create an errorlevel= 1
    echo huhu | findstr ha
    if %ERRORLEVEL% NEQ 0 set exitcode=%ERRORLEVEL%
    rem create an errorlevel= 0
    echo huhu | findstr hu
    if %ERRORLEVEL% NEQ 0 set exitcode=%ERRORLEVEL%
    exit %exitcode%

(error_exitcode_2.opsiscript)

bash

    [ShellInAnIcon_lin_exit1]
    set -x
    EXITCODE=0
    # create an exit code= 1
    echo huhu | grep ha
    EC=$?; if [ $EC -ne 0 ]; then EXITCODE=$EC; fi
    # create an exit code= 0
    echo huhu | grep hu
    EC=$?; if [ $EC -ne 0 ]; then EXITCODE=$EC; fi
    exit $EXITCODE

## Errordetection 1: Exitcode 3b

In powershell ist folgende Formulierung hilfreich um (z.B.) den Befehl:
`get-partition | select disknumber, partitionnumber, driveletter, size,type`
auszuführen:

    Execwith_ps_partitions powershell.exe

    [Execwith_ps_partitions]
    trap { write-output $_ ; exit 1 }
    get-partition | select disknumber, partitionnumber, driveletter, size,type
    exit $LASTEXITCODE

## Errordetection 1: Exitcode 4

Methoden:

    shellCall (<command string>) :string (exitcode)  [W/L]

Führt den Befehl `<command string>` mit der Standard Shell (cmd / bash) aus und liefert den Exitcode als String zurück.

(error_exitcode_3.opsiscript)

Beispiel:

    set $exitcode$ = shellCall('echo huhu | findstr ha')

Ist unter Windows eine Abkürzung für den Ausdruck:

    DosInAnIcon_netstart winst /sysnative
    set $exitcode$ = getLastExitcode

    [DosInAnIcon_netstart]
    echo huhu | findstr ha
    exit %ERRORLEVEL%

## Errordetection 1: Exitcode 5

(error_exitcode_3.opsiscript)

    set $exitcode$ = shellCall('echo huhu | grep ha')

Ist unter Linux eine Abkürzung für den Ausdruck:

    shellInAnIcon_ping
    set $exitcode$ = getLastExitcode

    [shellInAnIcon_netstart]
    echo huhu | grep ha || exit $?

Nochmal unser powershell Beispiel mit `shellCall`:

    shellCall('powershell.exe -Command "trap { write-output $_ ; exit 1 } ; get-partition | select disknumber, partitionnumber, driveletter, size,type ; exit $LASTEXITCODE"')

## Errordetection 1: Exitcode 6

Methoden:

    startProcess(<string>) :string (exitcode)  [W/L]

Startet das Programm `<string>` als Prozess und liefert den Exitcode zurück.

Beispiel:

    set $exitcode$ = startProcess('setup.exe /S')

Ist eine Abkürzung für den Ausdruck:

    Winbatch_setup
    set $exitcode$ = getLastExitcode

    [Winbatch_setup]
    setup.exe /S

## Errordetection 2: markErrorNumber

Methoden:

    markErrorNumber : noresult [W/L]
    errorsOccurredSinceMark <relation> <integer> : boolean [W/L]
    LogError <error - string> [W/L]

Beispiel: (error_markerror_0.opsiscript)

    markErrorNumber
    logError "test error"
    if errorsOccurredSinceMark > 0
        comment "error occured"
    else
        comment "no error occured"
    endif

## Fehlerauswertung 1

Methoden:

    isFatalError [W/L]
    isSuspended [W/L]
    isSuccess [W/L]
    noUpdateScript [W/L]

## Fehlerauswertung 2: isFatalError 1

    isFatalError
    isFatalError <short message"

Nach dem der Befehl aufgerufen wurde, werden keine Anweisungen mehr ausgeführt und als Skriptergebnis wird failed zurückgeliefert. Wird dieser Befehl nicht aufgerufen, so ist das Skriptergebnis success.

## Fehlerauswertung 2: isFatalError 2

Machmal ist es nicht gewünscht nach dem ersten Fehler abzubrechen, aber trotzdem am Ende das Script mit einem failed zu beenden.

Das ist insbesondere bei Umfangreichen Installationen / Konfigurationen der Fall.

    DefStringList $ErrorList$
    DefVar $fatal_error$

    ShellInAnIcon_config_depotadmin
    if not("0" = getLastExitCode)
      LogError "failed config_depotadmin"
      set $fatal_error$ = "true"
      set $errorList$ = addtolist($errorList$, " failed config_depotadmin")
    endif

    if count($errorList$) > "0"
      logError "Error summary:"
      for %akterror% in $errorList$ do LogError "%akterror%"
    endif

    if $fatal_error$ = "true"
      isFatalError
    endif

## Fehlerauswertung 3

- `isSuccess` //since 4.11.3.7 [W/L]
  Abort the script as successful.
- `noUpdateScript` //since 4.11.3.7 [W/L]
  Do not run a update script after setup even if there is one.
- `isSuspended` //since 4.11.4.1 [W/L]
  Abort the script without notice to the server. The action request remain unchanged.

← →

/

Go to slide: #