Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

6.4 Add host statistics, autosave, and regex search

Load Linux host and process metrics (linStat), automatic setpoint persistence (autosave), and regular-expression database inspection (retools) through iocsh.bash and the shared commonIocsh startup scripts. Unlike Run your first IOC, where runtime writes reset when the Input/Output Controller (IOC) stops, autosave restores your written process variable (PV) value across restarts over Channel Access (CA) and pvAccess (PVA).

Prerequisites

Open two Bash terminals on the same host with these roles and settings:

TerminalRoleWorking directoryEnvironment
Terminal 1IOC (iocsh.bash)~/ioc-training/loader_services/source "$TREE/setEpicsEnv.bash", export EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST=127.0.0.1, export EPICS_PVA_AUTO_ADDR_LIST=NO EPICS_PVA_ADDR_LIST=127.0.0.1
Terminal 2CA and PVA clientAny directorysource "$TREE/setEpicsEnv.bash", export EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST=127.0.0.1, export EPICS_PVA_AUTO_ADDR_LIST=NO EPICS_PVA_ADDR_LIST=127.0.0.1

Create the setpoint database and service startup

  1. In both terminals, activate your EPICS-env 1.5.0 tree and direct CA and PVA searches to loopback. If you installed the distribution outside ~/epics, set TREE to that installation’s directory instead of the second line:

    HOST_ID="$(. /etc/os-release && printf '%s-%s' "$ID" "$VERSION_ID")"
    TREE="$HOME/epics/1.5.0/$HOST_ID/7.0.10"
    source "$TREE/setEpicsEnv.bash"
    export EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST=127.0.0.1
    export EPICS_PVA_AUTO_ADDR_LIST=NO EPICS_PVA_ADDR_LIST=127.0.0.1
    
  2. In terminal 1, create a service directory outside the distribution:

    mkdir -p ~/ioc-training/loader_services
    cd ~/ioc-training/loader_services
    
  3. In ~/ioc-training/loader_services/, save this database as setpoint.db:

    record(ao, "$(P)Setpoint") {
        field(DESC, "Saved temperature setpoint")
        field(EGU, "degC")
        field(VAL, "20")
        field(PINI, "YES")
        info(autosaveFields, "VAL")
    }
    

    field(PINI, "YES") processes the analog output (ao) record once during iocInit so its alarm severity clears to NO_ALARM after boot-time restore. info(autosaveFields, "VAL") marks VAL for automatic request-file generation by autosave.iocsh.

  4. Save this startup file as st.cmd beside setpoint.db:

    on error break
    module linStat
    module autosave
    module retools
    
    epicsEnvSet("IOC", "LOADER_SVC")
    epicsEnvSet("IOCSH_TOP", "$(EPICS_MODULES)/commonIocsh")
    epicsEnvSet("AS_TOP", "./var")
    
    iocshLoad("$(IOCSH_TOP)/iocsh/linStat.iocsh")
    iocshLoad("$(IOCSH_TOP)/iocsh/autosave.iocsh")
    dbLoadRecords("setpoint.db", "P=$(IOC):")
    iocInit()
    

    Each setting coordinates iocsh.bash with commonIocsh:

    • module linStat, module autosave, and module retools load those libraries and export LINSTAT, AUTOSAVE, and RETOOLS automatically.
    • IOC is set to LOADER_SVC without a trailing colon. autosave.iocsh uses $(IOC) as a directory name under ./var/LOADER_SVC/ and builds the status prefix LOADER_SVC-as:, while linStat.iocsh supplies its own colon in LOADER_SVC:UPTIME and LOADER_SVC:PROCESS_ID. Passing P=$(IOC): to dbLoadRecords keeps $(P)Setpoint aligned with the trailing-colon P macro used across Chapters 3, 4, and 6.
    • Do not load linStat.iocsh together with iocStatsAdmin.iocsh in the same IOC. Both fragments define identically named host and process records such as $(IOC):UPTIME and $(IOC):FD_CNT.
  5. Preview the generated startup in terminal 1:

    iocsh.bash -n st.cmd
    

Save a setpoint and inspect live services

  1. In terminal 1, start the first IOC run from ~/ioc-training/loader_services/:

    iocsh.bash st.cmd
    

    During the initial boot into an empty ./var directory, dbrestore.c reports that ./var/LOADER_SVC/save/settings.sav does not exist yet. After iocInit() completes, afterIocRunning generates ./var/LOADER_SVC/req/settings.req from info(autosaveFields, "VAL") and starts a 5-second monitor set.

  2. At the iocsh prompt in terminal 1, filter loaded record names with reGrep:

    reGrep("LOADER_SVC:(Setpoint|PROCESS_ID|FD_CNT|UPTIME)")
    

    reGrep matches full record names against a regular expression and prints the four matching records:

    LOADER_SVC:Setpoint
    LOADER_SVC:PROCESS_ID
    LOADER_SVC:FD_CNT
    LOADER_SVC:UPTIME
    

    Unlike dbgrep, which uses shell-style * wildcards, reGrep requires the pattern to match the entire record name (.*Setpoint.* or an explicit prefix such as LOADER_SVC:.*).

  3. In terminal 2, read the initial setpoint, linStat process metrics, and autosave status records:

    caget LOADER_SVC:Setpoint LOADER_SVC:PROCESS_ID LOADER_SVC:FD_CNT LOADER_SVC:UPTIME
    caget LOADER_SVC-as:SR_0_Name LOADER_SVC-as:SR_statusStr
    

    LOADER_SVC:Setpoint starts at 20, while linStat reports the live IOC process ID (PID), open file-descriptor count, and uptime. PROCESS_ID and FD_CNT read 0 until their first scan; repeat the read after a few seconds:

    LOADER_SVC:Setpoint            20
    LOADER_SVC:PROCESS_ID          361766
    LOADER_SVC:FD_CNT              33
    LOADER_SVC:UPTIME              2 S
    LOADER_SVC-as:SR_0_Name        settings
    LOADER_SVC-as:SR_statusStr     Enabling list...
    
  4. Write 37.5 to LOADER_SVC:Setpoint and wait 6 seconds past the default 5-second SETTINGS_PERIOD save interval:

    caput LOADER_SVC:Setpoint 37.5
    sleep 6
    

    CA confirms the setpoint update:

    Old : LOADER_SVC:Setpoint            20
    New : LOADER_SVC:Setpoint            37.5
    
  5. Inspect the generated request file and saved value file on disk:

    cat ~/ioc-training/loader_services/var/LOADER_SVC/req/settings.req
    cat ~/ioc-training/loader_services/var/LOADER_SVC/save/settings.sav
    

    settings.req lists the tagged field and settings.sav stores 37.5 before <END>:

    LOADER_SVC:Setpoint.VAL
    # autosave R5.3	Automatically generated - DO NOT MODIFY - 261111-102556
    LOADER_SVC:Setpoint.VAL 37.5
    <END>
    
  6. In terminal 1, stop the first IOC run:

    exit
    

Verification

  1. In terminal 1, start a second IOC run from ~/ioc-training/loader_services/:

    iocsh.bash st.cmd
    
  2. Without writing to the record, read LOADER_SVC:Setpoint in terminal 2 through CA:

    caget LOADER_SVC:Setpoint LOADER_SVC:Setpoint.SEVR
    

    autosave restores 37.5 during iocInit, and PINI clears the record alarm state to NO_ALARM:

    LOADER_SVC:Setpoint            37.5
    LOADER_SVC:Setpoint.SEVR       NO_ALARM
    
  3. Read the restored record through PVA:

    pvxget LOADER_SVC:Setpoint
    

    pvxget confirms value double = 37.5 and alarm.severity int32_t = 0:

    LOADER_SVC:Setpoint
        value double = 37.5
        alarm.severity int32_t = 0
        alarm.status int32_t = 0
        alarm.message string = ""
        timeStamp.secondsPastEpoch int64_t = 1794421561
        timeStamp.nanoseconds int32_t = 770665617
        timeStamp.userTag int32_t = 0
        display.limitLow double = 0
        display.limitHigh double = 0
        display.description string = "Saved temperature setpoint"
        display.units string = "degC"
        display.precision int32_t = 0
        display.form.index int32_t = 0
        display.form.choices string[] = {7}["Default", "String", "Binary", "Decimal", "Hex", "Exponential", "Engineering"]
        control.limitLow double = 0
        control.limitHigh double = 0
        valueAlarm.lowAlarmLimit double = nan
        valueAlarm.lowWarningLimit double = nan
        valueAlarm.highWarningLimit double = nan
        valueAlarm.highAlarmLimit double = nan
    

    In Run your first IOC, water.db returns to 0 on every restart because no save set writes changes to disk. Enter exit in terminal 1 when finished.