Executing explicit commands
Command cmd
allows to directly execute one or more commands on FortiGate CLI and return the results. The common
use case is when we need to keep executing couple of commands in a cycle. There are two possible subcommands out
of which one must be used:
direct
Execute one or more commands directly specified on command line.xml
Use a special XML file to control what commands are executed.
Subcommand direct
is a limited version of xml
subcommand, however the user does not need to create the XML file.
Instead the user specifies commands in special format on command line and program creates temporal XML file
in its memory. In this case some settings and variables normally used with xml
subcommand can be also used.
By default all commands are executed in the same SSH session, so it is possible to call related commands like
diag deb flow ...
, diag sys profile ...
, etc. Only if explicitly specified, the commands are executed
simultaneously in multiple sessions.
Shared parameters
There are some parameters that are common for both subcommands. Those are specified directly after the cmd
keyword:
--setting
Override a setting specified in XML script (also works for temporal in‑memory scripts automatically created withcmd direct
subcommand.--variable
Override a variable specified in XML script (also works for in‑memory scripts).--iterations
Maximum number of cycles to execute. By default 0, which means "unlimited".--interval
Shortcut for--setting cycleDuration:{duration}
.--human
Generate output more comfortable for human reading it. By default the output is generated in the form compatible with Lab parsers but this paramter changes it.
cmd direct
Meant for quick & simple execution of multiple commands in a cycle.
By default all commands are executed in the global context, but it can be changed for all subsequent commands
on the command line by using --mgmt-vdom
parameter to execute them in the context of current
management VDOM or --vdom name
to execute in the context of specified VDOM. To switch back to global context
use --global
parameter.
Use --timeout
to change the default command timeout of 5 seconds to something else. Be aware that this
timeout triggers when there are no data sent in during the interval and it does not limit the execution
time of a command which is printing some output periodically and more often than once in 5 seconds by default.
By default the commands are executed every 60 seconds until the program is stopped. To change the cycle
duration use a XML script setting cycleDuration
(see bellow for XML script parameters description) or
use the shortcut parameter --interval
. Its value must contain the units, for example 10s
for ten seconds or
5m30s
for five and half minutes.
Example
Requirements:
- Repeat all the commands every 30 seconds.
- Stop after three iterations.
- First execute "get system status" and "get system performance status" in global context.
- Then execute "diagnose ip address list" in the VDOM context of whatever the current management VDOM is.
- Then execute "diagnose ip arp list" in the VDOM context of the VDOM called "root".
- And at the end execute "diag sys top" command in the global context again.
We want the "diag sys top" command to collect the processes for 10 seconds and show 1 result set with 30 lines output, so we must run it with its internal parameters "10 30 1". If we didn't specify the last "1" the command would never exit and it would timeout after default 5 seconds configured in flhcli. However in this case even when we limited the execution time of "diag sys top", it will need slightly more than 10 seconds to print each output, which is 5 seconds more than the default "read" timeout in flhcli. For that reason we need to increase the flhcli timeout at least to 11 seconds, but in real production environment it is better to set more, just in case.
Following command can be used to collected the required information. Notice that --redirect
parameter
is used to save the output into a separate file.
Also notice that --merge-stderr
parameter is used. This is because the "diag sys top" command does
not print its output to standard output stream which is the only one collected by flhcli by default.
With this parameter the error stream is also collected and merged with the standard stream. However,
be careful to use this parameter only when you know there are no real errors in your script, otherwise
this can cause program malfunction.
flhcli --redirect test.txt --merge-stderr cmd --iterations 3 --interval 30s direct \
"get system status" "get system performance status" \
--mgmt-vdom \
"diagnose ip address list" \
--vdom root \
"diagnose ip arp list" \
--global --timeout 11s \
"diag sys top 10 30 1"
[2020-05-12 13:53:37 +0200] Selected device "3980" xx.x.xx.xx:22 (maximum 4 simultaneous connections)
[2020-05-12 13:53:37 +0200] Starting new cycle at 2020-05-12 13:53:37.777809 +0200 CEST m=+0.002982019
[2020-05-12 13:53:51 +0200] Cycle took 13.484111774s, will sleep for 16.515888226s
[2020-05-12 13:54:07 +0200] Starting new cycle at 2020-05-12 13:54:07.781448 +0200 CEST m=+30.006562384
[2020-05-12 13:54:20 +0200] Cycle took 12.848891432s, will sleep for 17.151108568s
[2020-05-12 13:54:37 +0200] Starting new cycle at 2020-05-12 13:54:37.784549 +0200 CEST m=+60.009604054
[2020-05-12 13:54:50 +0200] Cycle took 12.847278226s, max iterations reached
The file "test.txt" contains the script output (in Lab plotter compatible format). Please be aware that this is not exact SSH console output - it is just formatted in that way using the outputs of collected FortiGate CLI commands.
device # # Cycle starting at 2020-05-12 13:53:37.777812 +0200 CEST m=+0.002984593
device # exe date
current date is: 2020-05-12
device # exe time
current time is: 13:53:38
last ntp sync:Fri Apr 12 13:53:38 2020
device (global) # get system status
Version: FortiGate-3980E v6.0.7,build0302,191112 (GA)
Virus-DB: 76.00716(2020-04-15 00:20)
[...]
device (global) # get system performance status
CPU states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
CPU0 states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
CPU1 states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
CPU2 states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
[...]
device (mgmt-vdom) # diagnose ip address list
IP=xx.x.xx.xx->xx.x.xx.xx/255.255.240.0 index=3 devname=mgmt1
IP=192.168.2.99->192.168.2.99/255.255.255.0 index=4 devname=mgmt2
[...]
device (root) # diagnose ip arp list
index=3 ifname=mgmt1 xx.x.xx.xxx 00:xx:xx:xx:xx:xx state=00000004 use=11 confirm=11 update=10 ref=4
device (global) # diag sys top 10 30 1
Run Time: 27 days, 1 hours and 35 minutes
0U, 0N, 0S, 100I, 0WA, 0HI, 0SI, 0ST; 258098T, 229785F
bcm.user 411 S < 18.9 0.0
miglogd 534 S 0.0 0.1
miglogd 579 S 0.0 0.1
[...]
device # # Cycle finished at 2020-05-12 13:53:51.160399 +0200 CEST m=+13.385545386
device # # Cycle took 12.770553627s
device # # Cycle starting at 2020-05-12 13:54:07.781449 +0200 CEST m=+30.006563227
device # exe date
current date is: 2020-05-12
device # exe time
current time is: 13:54:07
last ntp sync:Fri Apr 12 13:54:07 2020
[...]
[...]
device # # Cycle finished at 2020-05-12 13:54:50.530268 +0200 CEST m=+72.755297701
device # # Cycle took 12.744474763s
cmd xml
This is similar to cmd direct
but the commands are specified in a XML script file,
together with default settings and variables. Also XML script command offers more
features, for example:
- Dynamic variables - the variables used in the script can be auto‑initialized (for example to the list of all NP6 ids in the FortiGate script is connected to, or the list of names of network interfaces that are up and have link, etc.).
- Foreach loops - Execute similar command for each variable in the list (mainly useful together with dynamic variables).
- Parallel processing - group of commands can be processed simultaneously, which can significantly decrease the time needed for script execution and improve accuracy.
Selecting XML file
The mandatory parameter for cmd xml
is --xml
which is the path to XML file (with
root element flhscript
). It can be any local path, but it can also be HTTP or HTTPs
URL.
If HTTPs is used and the remote certificate is not successfully validated against a trusted
certification authority, the program will fail unless you also specify the insecure
parameter.
In case of HTTP URL or insecure
parameter enabled, program will print a big and
scary warning message and will pause for 60 seconds. In such case it is better to download
the XML script file manually, verify it and then use the local path to that file.
Selecting a cycle
One XML file can contain multiple different sets of commands to execute - called cycles.
If --cycle
parameter is not present, program will try to find the cycle "default"
and execute it. If such cycle does not exist, it will print an error and terminate.
XML file format
XML script file should validate against XML Schema Definition file. Any validation tool can be used, for example this one.
The XML script file is composed of 3 blocks, each of them can repeat:
<settings name="...">
Contains the global settings. Can be overriden from command line using --setting
parameters. Name is used to later attach the right settings to the cycle.
Possible settings with their default values:
setting name | default value | meaning |
---|---|---|
cycleDuration | 60s | minimal length of the cycle, sleep if executed faster |
ics | 100ms | inter-command sleep - how long to wait between two commands |
<parameters name="...">
This section defines "variables" that can be used inside the command strings. The name must be unique and it is used to select the right namespace inside a cycle.
Subelements can be:
<list name="...">
Specifies an array of values iterable inside the script though<foreach>
element. They can be specified either statically using<static>
subelement(s) or as dynamic array using<query type="...">
subelement. The later one can have<option name="...">
subelement(s) to control the specific query behavior. It can also be combination of both.<variable name="...">
A single & simple variable defined either internally in the script or via--variable
command line parameter. Both ways can be used at the same time to have a default value if--variable
parameter is not used on command line.
Dynamic array queries:
query type | example values | meaning | additional options (type;default;description) |
---|---|---|---|
np6ids | 0 1 2 3 | all NP6 chip ID in the device | --- |
np7ids | 0 1 | all NP7 chip ID in the device | --- |
interfacesUp | port1 port2 mgmt1 | interfaces up & with link |
|
vdoms | root test | defined VDOMS |
|
policies | 1 2 5 11 53 | configured policy IDs |
|
pids | 3206 224 | pid(s) of process |
|
<cycle name="..." parameters="..." settings="...">
Cycle specifies the commands to execute. It must refer to (possibly empty) <parameters>
and <settings>
blocks.
Its subcommands can be:
<echo>
To display text on console. This is useful to inform the user about script progress when output is redirected to file.<sleep>
Pause execution for specified amount of time.<command context="..." vdom="..." timeout="...">
Execute command. By default in global context with 5 seconds read timeout. Context can be specified in optionalcontext
attribute (with valuesglobal
orvdom
). If VDOM context is used, the current management VDOM is automatically selected unlessvdom
attribute is used as well. Timeout can be changed withtimeout
attribute with interval specified as value. Thevdom
attribute and command (element text) itself can contain variables specified "inband" using${name}
notation.<foreach list="..." variable="...">
Iterate though the specified list and execute all subelements as many times as the number of items in the list, every time with the current item stored in specified variable name. Be aware that dynamic lists are by default evaluated only when the program starts. If it is necessary to re-evaluate the dynamic list every cycle before theforeach
element, the optional attributeupdate="true"
must be used.<foreach>
can contain all the subelements the cycle can contain including nested<foreach>
elements.<parallel>
Can only contain<command>
subelements and executes them simultaneously. The number of parallel commands that will be running at the same time is the number of maximal connections allowed to the FortiGate. The script will not continue until all commands in theparallel
block are finished.
Dynamic variables
Dynamic variables are special variables with name starting with #
. These are not related to variables
described above in <parameters>
element. They can be used as a part of <command>
or <echo>
elements.
Dynamic variable can be seen as special internal command whose output is used on a place where
this variable is used. Every dynamic variable can have completely different purpose but they all follow the
same formatting - start with #
and possible parameters are divided by :
. Number and type of parameters
depend on each specific dynamic variable.
Following dynamic variables are recognized:
${#date:timezone:format}
Outputs current date and/or time formatted according to format
part as it is seen in timezone
specified by timezone
part.
Format must be specified in standard strftime format. Current date
format can be for example %Y-%m-%d
.
Timezone must be either one of the IANA defined timezones
(for example Europe/Prague
) or UTC
. It can also be empty (#date::format
), in which case the timezone
of the computer the program is running on will be used. Be careful with timezone names because they are
case sensitive (europe/prague
for example will result in INVALID-TIMEZONE
).
For details see Show part of crashlog that was generated today example below.
Examples
Run few simple commands
- No parameters needed, but the profile must exist anyway.
- No settings configured, defaults will be used, but the profile must exist anyway.
- Execute some simple commands in global context and some in VDOM context.
- Execute
diag sys top
command with collection time of 10 seconds and allow only three iterations (otherwise it would never end). Because it can take slightly more than 10 seconds to print each output, it is necessary to increase (read) timeout from default 5 seconds to 12 seconds. - Because
diag sys top
does not print to standard output stream, don't forget to enable global flhcli parameter--merge-stderr
when running the application. However, do not use this parameter automatically because sometimes errors returned by FortiGate can break the output stream and cause the program to malfunction. - Use
<sleep>
to pause for exactly one second for CPU profiling (inter-command sleep is substracted automatically from given sleep value to sleep for the right time, provided that ics is always smaller than sleep vaule).
<flhscript version="1">
<parameters name="default"/>
<settings name="default"/>
<cycle name="default" parameters="default" settings="default">
<command context="global" >get system perf stat</command>
<command context="vdom" >diag ip address list</command>
<command context="global" timeout="12s">diag sys top 10 15 3</command>
<command context="global">diag sys profile start</command>
<sleep>1s</sleep>
<command context="global">diag sys profile stop</command>
<command context="global">diag sys profile show</command>
</cycle>
</flhscript>
Execute as (with commands output redirection to "test.txt"):
flhcli --redirect test.txt --merge-stderr --name 3980 cmd xml --xml sample.xml
[2020-05-12 21:11:36 +0200] Selected device "3980" xx.x.xx.xx:22 (maximum 4 simultaneous connections)
[2020-05-12 21:11:36 +0200] Starting new cycle at 2020-05-12 21:11:36.33211 +0200 CEST m=+0.002633949
[2020-05-12 21:12:10 +0200] Cycle took 34.601869407s, will sleep for 25.398130593s
[2020-05-12 21:12:36 +0200] Starting new cycle at 2020-05-12 21:12:36.334717 +0200 CEST m=+60.005078989
[...]
Parts from "test.txt":
device # # Cycle starting at 2020-05-12 21:11:36.332112 +0200 CEST m=+0.002636091
device # exe date
current date is: 2020-05-12
device # exe time
current time is: 21:11:36
last ntp sync:Fri Apr 12 21:11:36 2020
device (global) # get system perf stat
CPU states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
CPU0 states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
CPU1 states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
CPU2 states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
CPU3 states: 0% user 0% system 0% nice 100% idle 0% iowait 0% irq 0% softirq
[...]
device (mgmt-vdom) # diag ip address list
IP=xx.x.xx.xx->xx.x.xx.xx/255.255.240.0 index=3 devname=mgmt1
IP=192.168.2.99->192.168.2.99/255.255.255.0 index=4 devname=mgmt2
[...]
device (global) # diag sys top 10 15 3
Run Time: 27 days, 8 hours and 53 minutes
0U, 0N, 0S, 100I, 0WA, 0HI, 0SI, 0ST; 258098T, 229787F
bcm.user 411 R < 15.8 0.0
forticron 544 S 0.4 0.0
snmpd 551 S 0.4 0.0
miglogd 534 S 0.0 0.1
[...]
device (global) # diag sys profile start
device (global) # diag sys profile stop
step=2, sz=16238956-4059739
device (global) # diag sys profile show
0xffffffff80208690: 5909 poll_idle
0xffffffff803b8500: 1 uart_chars_in_buffer
0xffffffffa01089e0: 4 np6_tbl_read_entry
0xffffffffa0121010: 1 np6_hw_hpe_exit
device # # Cycle finished at 2020-05-12 21:12:10.831764 +0200 CEST m=+34.502194379
device # # Cycle took 33.883693428s
device # # Cycle starting at 2020-05-12 21:12:36.334718 +0200 CEST m=+60.005080121
device # exe date
current date is: 2020-05-12
device # exe time
current time is: 21:12:36
last ntp sync:Fri Apr 12 21:12:36 2020
[...]
Iterate though all NP6 IDs
- Parameters section contains query "ifaceUp" with option to not include NP6 vlink interfaces.
- Execute "diag hardware device nic" command for every interface that is up and has a link.
- Print information message before each command execution.
- Cycle repeats every 10 seconds.
<flhscript version="1">
<parameters name="default">
<list name="ifacesUp">
<query type="interfacesUp">
<option name="np6vlinks">no</option>
</query>
</list>
</parameters>
<settings name="default">
<cycleDuration>10s</cycleDuration>
</settings>
<cycle name="nics" parameters="default" settings="default">
<foreach list="ifacesUp" update="true" variable="iface">
<echo>Processing interface ${iface}</echo>
<command context="global">diag hardware device nic ${iface}</command>
</foreach>
</cycle>
</flhscript>
Execute with the right cycle name (notice the execution+sleep time is 10 seconds because cycleDuration
was defined in the XML file settings):
flhcli --redirect test.txt --name 3980 cmd xml --xml sample.xml --cycle nics
[2020-05-12 21:21:47 +0200] Selected device "3980" xx.x.xx.xx:22 (maximum 4 simultaneous connections)
[2020-05-12 21:21:48 +0200] Starting new cycle at 2020-05-12 21:21:48.222871 +0200 CEST m=+0.789261966
[2020-05-12 21:21:49 +0200] Processing interface mgmt1
[2020-05-12 21:21:49 +0200] Processing interface port1
[2020-05-12 21:21:49 +0200] Processing interface port2
[2020-05-12 21:21:49 +0200] Processing interface port13
[2020-05-12 21:21:49 +0200] Processing interface port14
[2020-05-12 21:21:49 +0200] Processing interface port15
[2020-05-12 21:21:49 +0200] Processing interface port16
[2020-05-12 21:21:50 +0200] Processing interface port17
[2020-05-12 21:21:50 +0200] Processing interface port18
[2020-05-12 21:21:50 +0200] Cycle took 2.172584478s, will sleep for 7.827415522s
[...]
Output from file:
device # # Cycle starting at 2020-05-12 21:21:48.222875 +0200 CEST m=+0.789265921
device # exe date
current date is: 2020-05-12
device # exe time
current time is: 21:21:49
last ntp sync:Fri Apr 12 21:21:49 2020
device (global) # diag hardware device nic mgmt1
Description Intel(R) Gigabit Ethernet Network Driver
Driver_Name igb
Driver_Version 5.0.6
[...]
Rx_Packets 282857950
Tx_Packets 3410230
Rx_Bytes 41343934170
Tx_Bytes 1175973132
[...]
device (global) # diag hardware device nic port1
Description :FortiASIC NP6 Adapter
Driver Name :FortiASIC Unified NPU Driver
Name :np6_0
PCI Slot :0000:84:00.0
[...]
Rx Pkts :850568431
Rx Bytes :1186411872241
Tx Pkts :2781542
Tx Bytes :311632533
[...]
device (global) # diag hardware device nic port2
Description :FortiASIC NP6 Adapter
[...]
device (global) # diag hardware device nic port13
Description :FortiASIC NP6 Adapter
Driver Name :FortiASIC Unified NPU Driver
[...]
device (global) # diag hardware device nic port14
Description :FortiASIC NP6 Adapter
Driver Name :FortiASIC Unified NPU Driver
[...]
device (global) # diag hardware device nic port15
Description :FortiASIC NP6 Adapter
Driver Name :FortiASIC Unified NPU Driver
[...]
device (global) # diag hardware device nic port16
Description :FortiASIC NP6 Adapter
Driver Name :FortiASIC Unified NPU Driver
[...]
device (global) # diag hardware device nic port17
Description :FortiASIC NP6 Adapter
Driver Name :FortiASIC Unified NPU Driver
Name :np6_0
[...]
device (global) # diag hardware device nic port18
Description :FortiASIC NP6 Adapter
Driver Name :FortiASIC Unified NPU Driver
Name :np6_1
[...]
device # # Cycle finished at 2020-05-12 21:21:50.29333 +0200 CEST m=+2.859715850
device # # Cycle took 1.284382624s
[...]
It is also possible to run exactly the same script, but override cycle duration on command line:
flhcli --redirect test.txt --name 3980 cmd --interval 5s xml --xml sample.xml --cycle nics
[2020-05-12 21:28:03 +0200] Selected device "3980" xx.x.xx.xx:22 (maximum 4 simultaneous connections)
[2020-05-12 21:28:04 +0200] Starting new cycle at 2020-05-12 21:28:04.454655 +0200 CEST m=+0.781283506
[2020-05-12 21:28:05 +0200] Processing interface mgmt1
[2020-05-12 21:28:05 +0200] Processing interface port1
[2020-05-12 21:28:05 +0200] Processing interface port2
[2020-05-12 21:28:05 +0200] Processing interface port13
[2020-05-12 21:28:05 +0200] Processing interface port14
[2020-05-12 21:28:05 +0200] Processing interface port15
[2020-05-12 21:28:06 +0200] Processing interface port16
[2020-05-12 21:28:06 +0200] Processing interface port17
[2020-05-12 21:28:06 +0200] Processing interface port18
[2020-05-12 21:28:06 +0200] Cycle took 2.298440369s, will sleep for 2.701559631s
Get all NP6 drop counters
- Parameters section contains query "np6ids".
- Cycle "np6" contains foreach element to execute the specified commands for each NP6 ID.
- Commands inside each cycle are executed simultaneously.
- When processing a new NP6 ID print a message to console.
- Global settings on defaults.
<flhscript version="1">
<parameters name="default">
<list name="np6auto">
<query type="np6ids"/>
</list>
</parameters>
<settings name="default"/>
<cycle name="np6" parameters="default" settings="default">
<foreach list="np6auto" variable="np6id">
<echo>Processing NP6 #${np6id}</echo>
<parallel>
<command context="global">diag npu np6 dce ${np6id}</command>
<command context="global">diag npu np6 anomaly-drop ${np6id}</command>
<command context="global">diag npu np6 hrx-drop ${np6id}</command>
<command context="global">diag npu np6 session-stats ${np6id}</command>
<command context="global">diag npu np6 sse-stats ${np6id}</command>
</parallel>
</foreach>
</cycle>
</flhscript>
Get hit counters for all IPv4 policies in all VDOMs
- Use "vdoms" query to get a list of all VDOMs
- Use "policies" query to get a list of IPv4 policies, cache them for 10 minutes (even if
update="true"
in<foreach>
). - Add also static policy ID "0" to the "policies" list to include implicit drop policy.
- Group entries in "policies4" list by (max) 10 - up to ten values at once separated by space.
- Use separate parameters profile to prevent expensive querying when using unrelated cycles.
- Use nested
<foreach>
to get a list of policies for each VDOM. Noticeupdate="true"
attribute to get the right policy list in each VDOM. - Global settings on defaults.
<flhscript version="1">
<parameters name="vdoms-and-policies">
<list name="vdoms">
<query type="vdoms"/>
</list>
<list name="policies4" group="10">
<query type="policies">
<option name="vdom">${vdom}</option>
<option name="version">4</option>
<option name="cache">10m</option>
</query>
<static>0</static>
</list>
</parameters>
<settings name="default"/>
<cycle name="policyhits" parameters="vdoms-and-policies" settings="default">
<foreach list="vdoms" variable="vdom">
<foreach list="policies4" variable="id" update="true">
<echo>Getting policy hits for VDOM ${vdom} policy IDs: ${id}</echo>
<command context="vdom" vdom="${vdom}">diag firewall iprope show 00100004 ${id} | grep ^idx=</command>
</foreach>
</foreach>
</cycle>
</flhscript>
Get stats file for all BGP processes
- Parameters section contains query "pids" asking for process name "bgpd".
- Cycle contains foreach element to execute the specified command for every running bgpd process.
- Attribute "update" in foreach section makes sure the right PIDs are used even if some process(es) crash.
- Global settings on defaults.
<flhscript version="1">
<parameters name="default">
<list name="bgpdPIDs">
<query type="pids">
<option name="process">bgpd</option>
</query>
</list>
</parameters>
<settings name="default"/>
<cycle name="default" parameters="default" settings="default">
<foreach list="bgpdPIDs" update="true" variable="pid">
<command context="global">fnsysctl cat /proc/${pid}/stat</command>
</foreach>
</cycle>
</flhscript>
Show part of crashlog that was generated today
- "Today" should be related to the timezone the FortiGate has configured because crashlog time is in FortiGate local timezone.
- If FortiGate has the same timezone configured as computer executing this, timezone can be omitted.
<flhscript version="1">
<parameters name="default"/>
<settings name="default"/>
<cycle name="default" parameters="default" settings="default">
<echo>Current time now in Tokyo is ${#date:Asia/Tokyo:%Y-%m-%dT%H:%M:%S}</echo>
<command context="global">diag debug crashlog read | grep ${#date::%Y-%m-%d}</command>
</cycle>
</flhscript>
Public XML scripts
There are some public XML scripts that can be used directly as flhcli cmd xml --xml https://fortilighthouse.com/scripts/....xml
or just as a source
of inspiration.
Please see public scripts index.
Ideas for more public scripts are welcome.