cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
5225
Views
0
Helpful
32
Replies

Script to inspect files in flash and create two sequential entries

Anthony LaRosa
Level 1
Level 1

What im trying to do:

1. Have the switch do a showtech every 2 hours

2. Send the showtech to flash

3. The first showtech will be techinfo1.txt

4. The second will be techinfo2.txt

5. The next showtech will overwrite techinfo1.txt

6. The next showtech will overwrite techinfo2.txt and so forth.

Is this possible? In the direction of regexpressions possibly?

Write now I have it appending to flash in one file and than once it hits a certain file size, clearing the file and restarting it. I don't like doing it like that.

::cisco::eem::event_register_timer cron name tech1 cron_entry 0 */2 ***

namespace import ::cisco::eem::*
namespace import ::cisco::lib::*


array set arr_einfo [event_reqinfo]

set x = file size flash:techinfo.txt

if {$x > 5242880}

file delete flash:techinfo.txt

else{

if [catch {cli_open} result] {
    error $result $errorInfo
} else {
    array set cli1 $result
}

if [catch {cli_exec $cli1(fd) "enable"} _cli_result] {
    error $_cli_result $errorInfo
}

if [catch {cli_exec $cli1(fd) "show tech-support | append flash:techinfo.txt"} _cli_result] {
    error $_cli_result $errorInfo
}

}

catch {cli_close $cli1(fd) $cli1(tty_id)} result

Credit to Joseph Clark for the applet converter

9 Accepted Solutions

Accepted Solutions

Joe Clarke
Cisco Employee
Cisco Employee

You can use file mtime for this:

set filename "flash:techinfo2.txt"

set now [clock seconds]

if { [file exists $filename] && [expr $now - [file mtime $filename]] < 14400 } {

    set filename "flash:techinfo1.txt"

}

# Send your output to $filename

View solution in original post

Your whole script is in a function that you never call.  Just remove the lines:

proc get_tech {} {

And the last '}' in the file.

View solution in original post

EEM Safe Tcl blocks the mtime command.  Try adding this line above the mtime line:

array set stat [file stat $filename]

Then change the mtime check to:

[expr $now - $stat(mtime)] < 14400

View solution in original post

You still have that array set line in there.  Do this.  Replace the line starting with "array set" with these lines:

if { [file exists $filename] } {

    file stat $filename sarr

    if { [expr $now - $sarr(mtime)] < 14400 } {

        set filename "newtech.txt"

    }

}

View solution in original post

You first have to make sure you set filename appropriately before you send the output of show tech to it.  I'm not sure you're doing that in your current script.  Then for rotation, this should work:

set filename "flash:tech1.txt"

set nfilename "flash:text2.txt"

if { [file exists $filename] } {

    cli_exec $cli(fd) "copy $filename $nfilename"

}

cli_exec $cli(fd) "show tech | redirect $filename"

If the policy is already running every two hours, flash:tech1.txt will contain the latest stuff, and flash:tech2.txt will contain the previous run.

View solution in original post

This line:

cli_exec $cli1(fd) "show tech | redirect $filename" _cli_result

Should be:

cli_exec $cli1(fd) "show tech | redirect $filename"

Or:

if { [catch {cli_exec $cli1(fd) "show tech | redirect $filename"} _cli_result] } {

    error $_cli_result $errorInfo

}

You'll also need to set file prompt quiet to remove the prompting:

if { [file exists $filename] } {

    cli_exec $cli1(fd) "config t"

    cli_exec $cli1(fd) "file prompt quiet"

    cli_exec $cli1(fd) "do copy $filename $nfilename"

    cli_exec $cli1(fd) "no file prompt quiet"

    cli_exec $cli1(fd) "end"

}

View solution in original post

The file prompt quiet suppresses the prompt, and thus the timeout problem should go away (unless, of course, it takes more than 20 seconds to generate the show tech).  If you still need more time, you'll need to add a maxrun argument to the end of your event registration line (e.g., maxrun 60).

View solution in original post

Weird.  The "do" copy worked in my test.  Okay, change your if block to this:

if { [file exists $filename] } {

    cli_exec $cli1(fd) "config t"

    cli_exec $cli1(fd) "file prompt quiet"

    cli_exec $cli1(fd) "end"

    cli_exec $cli1(fd) "copy $filename $nfilename"

    cli_exec $cli1(fd) "config t"

    cli_exec $cli1(fd) "no file prompt quiet"

    cli_exec $cli1(fd) "end"

}

View solution in original post

The redirect is likely triggering another prompt.  After the copy, add:

cli_exec $cli1(fd) "delete /force $filename"

View solution in original post

32 Replies 32

Joe Clarke
Cisco Employee
Cisco Employee

You can use file mtime for this:

set filename "flash:techinfo2.txt"

set now [clock seconds]

if { [file exists $filename] && [expr $now - [file mtime $filename]] < 14400 } {

    set filename "flash:techinfo1.txt"

}

# Send your output to $filename

Thanks for your response Joe.

Right now this is what I have. I will be using an applet countdown to trigger it but for now I am trying to run it manually.

Below is the script. When I run it I am not getting any file created in flash.

::cisco::eem::event_register_none

#Namespace Imports

namespace import ::cisco::eem::*

namespace import ::cisco::lib::*

proc get_tech {} {

array set arr_einfo [event_reqinfo]

#Set Variable Filename

set filename "flash:oldtech.txt"

#set timer in seconds allowing it to be used for relative time calculations

set now [clock seconds]

#Send Showtech Output to Flash Filename Variable


if [catch {cli_exec $cli1(fd) "show tech-support | flash:$filename"} _cli_result] {

    error $_cli_result $errorInfo

}

if [catch {cli_open} result] {

    error $result $errorInfo

} else {

    array set cli1 $result

}

#Determine File Name Through Age Comparison

if { [file exists $filename] && [expr $now - [file mtime $filename]] < 14400 } {

    set filename "flash:newtech.txt"

}

catch {cli_close $cli1(fd) $cli1(tty_id)} result

}

I turned on logging and this is what I get:

Switch#event manager run showtech.tcl

Switch#

*Dec  9 10:44:36.737: cli_history_entry_add: free_hist_list size=0, hist_list size=7

*Dec  9 10:44:36.737: check_eem_cli_policy_handler: command_string=event manager run showtech.tcl

*Dec  9 10:44:36.737: check_eem_cli_policy_handler: num_matches = 0, response_code = 1

*Dec  9 10:44:36.737: fh_fd_none_event_match: parameters = , sync = 1, get_tty = 1, tty_buf = 0

*Dec  9 10:44:36.737: none_conn_tm_alloc: ptp=0x3A4FF4D4

*Dec  9 10:44:36.737: fh_fd_none_event_match: publish_timer=0x349E7480, ptp=0x3A

Switch#4FF4D4, max_delay=30000

*Dec  9 10:44:36.737: none_conn_tm_add: re=0x3A500854, ptp=0x3A4FF4D4

*Dec  9 10:44:36.737: fh_fd_none_event_match: re = 0x3A500854, num_matches = 1

*Dec  9 10:44:36.737: fh_send_server_sig_hndlr: received a pulse from none on node0/0 with fdid: 11

*Dec  9 10:44:36.737: fh_send_none_fd_msg: msg_type=64

*Dec  9 10:44:36.737: fh_send_none_fd_msg: sval=0

*Dec  9 10:44:36.737: fh_send_server_sig_hndlr: received FH_MSG_EVENT_PUBLISH_SYNC

*Dec  9 10:44:36.737: EEM: server processe

Switch#s multi events: timewin=1, sync_flag=1, ec_index=0, cmp_occ=1

*Dec  9 10:44:36.737: EEM: ctx=5:(5,1,1)

*Dec  9 10:44:36.737: EEM: server processes multi events: corr_res=1, cur_tcnt=1, cmp_tcnt=1

*Dec  9 10:44:36.737: fh_schedule_policy: prev_epc=0x0; epc=0x3A48397C

*Dec  9 10:44:36.737: EEM server schedules scripts

*Dec  9 10:44:36.737: EEM server schedules one event: policy_type=script epc=3A48397C.

*Dec  9 10:44:36.737: EEM: server schedules a policy: policyname=tmpsys:/eem_policy/showtech.tcl

*D

Switch#ec  9 10:44:36.738: spawn script tmpsys:/eem_policy/showtech.tcl

*Dec  9 10:44:36.738: EEM policy tmpsys:/eem_policy/showtech.tcl has been scheduled to run

*Dec  9 10:44:36.738: fh_spawn: -FMRUN -FMSAFE tmpsys:/lib/tcl/base.tcl tmpsys:/eem_policy/showtech.tcl

*Dec  9 10:44:36.738: fh_tcl_spawn: argc=5, argstr=-FMRUN, stdin=0, stdout=0,stderr=0, priority=4, eid=5

*Dec  9 10:44:36.738: pid for spawned process is 224. fdid: 11 sn: 4 jobid: 7

*Dec  9 10:44:36.739: fh_tcl_get_mode: mode = 1, StartupScript

Switch#= tmpsys:/lib/tcl/base.tcl, RealScript = tmpsys:/eem_policy/showtech.tcl

*Dec  9 10:44:36.739: fh_set_tclpath_global: tcl_library is set to tmpsys:/lib/tcl

*Dec  9 10:44:36.739: fh_set_tclpath_global: auto_path is set to tmpsys:/eem_lib_user tmpsys:/eem_lib_system

*Dec  9 10:44:36.747: fh_io_msg: received FH_MSG_API_INIT; jobid=22, processid=224, client=12, job name=EEM TCL Proc

*Dec  9 10:44:36.747: fh_register_evreg_cmds: tctx=35173CE4, dummy=1

*Dec  9 10:44:36.748: fh_tcl_compile_policy: evaluating

Switch# policy: startup_scriptname=tmpsys:/lib/tcl/base.tcl, real_scriptname=tmpsys:/eem_policy/showtech.tcl

*Dec  9 10:44:36.749: fh_tcl_slave_interp_init: interp=3A2FE728, tctx=35173CE4, fh_mode=1, real=tmpsys:/eem_policy/showtech.tcl, curr=showtech.tcl

*Dec  9 10:44:36.754: fh_register_evreg_cmds: tctx=35173CE4, dummy=1

*Dec  9 10:44:36.995: fh_server: fh_io_msg: received msg FH_MSG_API_CLOSE from client 12 pclient 12

*Dec  9 10:44:36.995: fh_io_msg: received FH_MSG_API_CLOSE client=12

*Dec  9 10:44:36.99

Switch#6: fh_tcl_assoc_data_delproc: freeing tctx=0x35173CE4

*Dec  9 10:44:37.010: received SIGCHLD pulse from child death pid=224

*Dec  9 10:44:37.010: received pulse from child death code=1; epc=0x3A48397C

*Dec  9 10:44:37.010: EEM policy showtech.tcl has completed with normal exit status of 0x0 exec_status=2 event_completion=0

*Dec  9 10:44:37.010: fh_send_none_fd_msg: msg_type=18

*Dec  9 10:44:37.010: fh_fd_none_publish_done: rc=0, re=3A500854

*Dec  9 10:44:37.010: fh_fd_none_publish_done: rc=0, publish

Switch#_expired=0

*Dec  9 10:44:37.010:   sid=5, ptp=0x3A4FF4D4, connp=0x3A3B34C8

*Dec  9 10:44:37.010: none_conn_tm_remove: re=0x3A500854, ptp=0x3A4FF4D4

*Dec  9 10:44:37.010: fh_fd_none_conn_tm_free: ptp=0x3A4FF4D4

*Dec  9 10:44:37.010: fh_send_none_fd_msg: sval=0

*Dec  9 10:44:37.010: EEM: server decrements in use thread: jobid=7 rule id=1 in use thread=0.

*Dec  9 10:44:37.010: fh_schedule_policy: prev_epc=0x3A48397C; epc=0x0

*Dec  9 10:44:37.010: EEM server schedules scripts

*Dec  9 10:44:37.010: EEM

Switch#server schedules sync same source events:fdid=11; sn=4.

*Dec  9 10:44:37.010: fh_fd_match_event: re=0x3A500854, policyname=showtech.tcl, parameters=, get_tty=1

Your whole script is in a function that you never call.  Just remove the lines:

proc get_tech {} {

And the last '}' in the file.

The script has been working as it should be it fills the bootflash with the deleted files which makes sense.

 

I modified the CLI section of the script to squeeze the bootflash but now it is not working.

I turned on debugging for all event manager and im not seeing any output at all

This is the CLI portion with changes:

if { [file exists $filename] } {delete

    cli_exec $cli1(fd) "config t"

    cli_exec $cli1(fd) "file prompt quiet"

    cli_exec $cli1(fd) "end"
   
    cli_exec $cli1(fd) "delete /force $nfilename"

    cli_exec $cli1(fd) "copy $filename $nfilename"

    cli_exec $cli1(fd) "delete /force $filename"

    cli_exec $cli1(fd) "squeeze bootflash:"

    cli_exec $cli1(fd) "config t"

    cli_exec $cli1(fd) "no file prompt quiet"

    cli_exec $cli1(fd) "end"

}

 

Does it look off to anyone?

 

 

First, run all of these commands manually to see what prompts you may get.  If you're getting any prompts, you will need to handle them.  Next, squeeze can take a few seconds, so you may need to increase your maxrun time for this policy to something like 45 or 60 seconds.

Yes, i did that and noticed that squeeze bootflash prompts twice

All deleted files will be removed. Continue? [confirm]
Squeeze operation may take a while. Continue? [confirm]

That's why I nested it in the CLI commands while the fileprompt quiet was still on. and then shut the file prompt after.

The runtime I had also increased previously.

 

Thanks for the quick reply

So if you run ALL of the commands including file prompt quiet, and the prompting still occurs, then you need to use cli_write to send the squeeze command and cli_read_pattern to wait for the prompt.  When you get the prompt, use cli_write again to send the appropriate response.  You can use cli_exec again when you are sure the result will be the router prompt.

Thanks,

When I manually run the script using cli command "event manager run showtech.tcl" , nothing at all is happening.

I turned on "debug event manager tcl cli" and then ran the script again.. no output in terminal.

I then turned on all event manager debuging and ran the script..still no output.

 

This is the script:

::cisco::eem::event_register_none maxrun 2200

#Namespace Imports

namespace import ::cisco::eem::*
namespace import ::cisco::lib::*


array set arr_einfo [event_reqinfo]


#Pass CLI Commands

if [catch {cli_open} result] {
    error $result $errorInfo
} else {
    array set cli1 $result
}

if [catch {cli_exec $cli1(fd) "enable"} _cli_result] {
    error $_cli_result $errorInfo
}

#Set Variables

set filename "flash:newtech.txt"

set nfilename "flash:oldtech.txt"


#Copy New File to Old at Next Instance

if { [file exists $filename] } {delete

    cli_exec $cli1(fd) "config t"

    cli_exec $cli1(fd) "file prompt quiet"

    cli_exec $cli1(fd) "end"
   
    cli_exec $cli1(fd) "delete /force $nfilename"

    cli_exec $cli1(fd) "copy $filename $nfilename"

    cli_exec $cli1(fd) "delete /force $filename"

    cli_exec $cli1(fd) "config t"

    cli_exec $cli1(fd) "no file prompt quiet"

    cli_exec $cli1(fd) "end"

    cli_write $cli1(fd) "squeeze bootflash:"

    cli_read_pattern $cli1(fd) "confirm"
   
    cli_write $cli1(fd) "confirm"

    cli_read_pattern $cli1(fd) "confirm"
   
    cli_write $cli1(fd) "confirm"

}

#Pipe Show-Technology to Set Variable

cli_exec $cli1(fd) "show tech | redirect $filename"


catch {cli_close $cli1(fd) $cli1(tty_id)} result

Sounds to me like either you didn't enable "term mon" or you are not logging at debug level to the monitor output.  Make sure you have the following configured:

 

logging monitor debug

 

Then make sure you run "term mon" on your VTY.  If you do that, you should see some output from the debugs when you run the policy.

Thanks. I've been debugging and testing and am hung up on this:

Switch#event manager run showtech.tcl

not allowed to invoke subcommand mtime of file

    while executing

"error $msg"

    (procedure "::safe::Subset" line 46)

    invoked from within

"file mtime $filename"

    invoked from within

"$slave eval $Contents"

    (procedure "eval_script" line 7)

    invoked from within

"eval_script slave $scriptname"

    invoked from within

"if {$security_level == 1} {       #untrusted script

     interp create -safe slave

     interp share {} stdin slave

     interp share {} stdout slave

..."

    (file "tmpsys:/lib/tcl/base.tcl" line 50)

Tcl policy execute failed: not allowed to invoke subcommand mtime of file

This is how the script currently looks:

::cisco::eem::event_register_none

#Namespace Imports

namespace import ::cisco::eem::*
namespace import ::cisco::lib::*


array set arr_einfo [event_reqinfo]


#Pass CLI Commands

if [catch {cli_open} result] {
    error $result $errorInfo
} else {
    array set cli1 $result
}

if [catch {cli_exec $cli1(fd) "enable"} _cli_result] {
    error $_cli_result $errorInfo
}

#set timer in seconds allowing it to be used for relative time calculations

set now [clock seconds]


#Set Variable Filename


set filename "oldtech.txt"


#Determine File Name Through Age Comparison


if { [file exists $filename] && [expr $now - [file mtime $filename]] < 14400 } {

    set filename "newtech.txt"
}


#Send Showtech Output to Flash Filename Variable


if [catch {cli_exec $cli1(fd) "show tech-support | redirect flash:$filename"} _cli_result] {
    error $_cli_result $errorInfo
}


catch {cli_close $cli1(fd) $cli1(tty_id)} result


EEM Safe Tcl blocks the mtime command.  Try adding this line above the mtime line:

array set stat [file stat $filename]

Then change the mtime check to:

[expr $now - $stat(mtime)] < 14400

That was correct.

Thanks for the help thus far.

The array set stat should be [file state filename VARname]

For the file name I first tried mtime because the script appeared to want it in the arguments.

That was not correct because it wants a directory or file to check which makes sense.

I then tested it with oldtech.txt. This seems to be in the correct direction.

It's complaining about the mtime in the arguments array again.

Any ideas?

Switch#event manager run showtech.tcl

can't read "stat(mtime)": no such element in array

    while executing

"expr $now - $stat(mtime)"

    invoked from within

"$slave eval $Contents"

    (procedure "eval_script" line 7)

    invoked from within

"eval_script slave $scriptname"

    invoked from within

"if {$security_level == 1} {       #untrusted script

     interp create -safe slave

     interp share {} stdin slave

     interp share {} stdout slave

..."

    (file "tmpsys:/lib/tcl/base.tcl" line 50)

Tcl policy execute failed: can't read "stat(mtime)": no such element in array

Here's where I am at:

#Determine File Name Through Age Comparison

array set stat [file stat oldtech.txt $filename]

if { [file exists $filename] && [expr $now - $stat(mtime)] < 14400 } {

    set filename "newtech.txt"
}

I confused Perl and Tcl behavior.  Perl returns the array, but Tcl allows you to fetch one stat parameter at a time.  So you want:

[expr $now - [file stat $filename mtime]]

Thanks Joe.

I am still having the arguments error that I encountered troubleshooting earlier.

Switch#event manager run showtech.tcl

wrong # args: should be "file stat name varName"

    while invoking

"file stat oldtech.txt"

    invoked from within

"::interp invokehidden slave file stat oldtech.txt"

    ("eval" body line 1)

    invoked from within

"eval ::interp invokehidden $slave $command $subcommand [lrange $args 1 end"

    (procedure "::safe::Subset" line 42)

    invoked from within

"file stat $filename"

    invoked from within

"$slave eval $Contents"

    (procedure "eval_script" line 7)

    invoked from within

"eval_script slave $scriptname"

    invoked from within

"if {$security_level == 1} {       #untrusted script

     interp create -safe slave

     interp share {} stdin slave

     interp share {} stdout slave

..."

    (file "tmpsys:/lib/tcl/base.tcl" line 50)

Tcl policy execute failed: wrong # args: should be "file stat name varName"

Current script from switch

Switch#show event manager policy registered detailed showtech.tcl

::cisco::eem::event_register_none

#Namespace Imports

namespace import ::cisco::eem::*
namespace import ::cisco::lib::*


array set arr_einfo [event_reqinfo]


#Pass CLI Commands

if [catch {cli_open} result] {
    error $result $errorInfo
} else {
    array set cli1 $result
}

if [catch {cli_exec $cli1(fd) "enable"} _cli_result] {
    error $_cli_result $errorInfo
}

#set timer in seconds allowing it to be used for relative time calculations

set now [clock seconds]


#Set Variable Filename


set filename "oldtech.txt"


#Determine File Name Through Age Comparison

array set stat [file stat $filename]

if { [file exists $filename] && [expr $now - [file stat $filename mtime]]
< 14400 } {

    set filename "newtech.txt"
}


#Send Showtech Output to Flash Filename Variable


if [catch {cli_exec $cli1(fd) "show tech-support | redirect flash:$filename"} _cli_result] {
    error $_cli_result $errorInfo
}


catch {cli_close $cli1(fd) $cli1(tty_id)} result

Review Cisco Networking for a $25 gift card