Ruby API monitor-traffic (etc.) didnt work

Hi,
I want read actual tx/rx on interface with ruby api. But it didnt return any result to variable, because it didnt stop. Sending “/cancel” didnt help. Problem is also described there:

http://www.aarongifford.com/computers/mtik/latest/doc/MTik.html > > Public Class Methods > command(args):
WARNING: If you use this call with an API command like “/tool/fetch“ or a similar command that generates replies until canceled, it will forever keep reading replies, never returning. So do NOT use this with any API command that does not complete with a “!done“ response without any additional interaction.

Does exist some solution or workaround?

Thanks

solution:
command1 will not work
command2 will work

#!/usr/bin/env ruby
require ‘rubygems’
require ‘mtik’
MTik::verbose = true
command1=[“/interface/monitor-traffic”,“=interface=ether1WAN”,“=.proplist=rx-bits-per-second,tx-bits-per-second”,“/cancel”]
command2=[[“/interface/monitor-traffic”,“=interface=ether1WAN”,“=.proplist=rx-bits-per-second,tx-bits-per-second”],[“/cancel”]]
p command = command1
p MTik::command(:host=>“testmk”,:user=>“ruby”,:pass=>“rruby”,:command=>command)

If you want to get stats only then send command with “once” parameter.
/interface/monitor-traffic
=interface=ether1WAN
=.proplist=rx-bits-per-second,tx-bits-per-second
=once=

Using the Ruby API library, one can also choose to cancel after a specific number of replies are received. Here’s how:

require 'rubygems'
require 'mtik'

# Be verbose in output
MTik::verbose = true

# Connect to the device:
connection = MTik::Connection.new :host => '10.0.0.1', :user => 'admin', :pass => 'password'

# We are going to send a "monitor-traffic" command that will keep sending
# output until we "cancel" the command.  We only want to receive 10 responses:
$reply_limit = 10

# Execute the command:
$reply_count = 0
connection.get_reply_each(
  "/interface/monitor-traffic",
  "=interface=ether1",
  "=.proplist=rx-bits-per-second,tx-bits-per-second"
) do |request_object, reply_sentence|
  if reply_sentence.key?('!re')  # We only pay attention to reply sentences
    # Print the reply sentence:
    p reply_sentence

    # Increment the reply counter:
    $reply_count += 1

    # If we've reached our reply goal, cancel:
    if $reply_count >= $reply_limit
      # Cancel this command request:
      request_object.cancel
    end
  end
end

connection.close

Here’s an example output (with verbose API output enabled):

<<< '/login' (6)
<<< '.tag=0' (6)
<<< END-OF-SENTENCE

>>> '!done' (5)
>>> 'ret=cb21408d7123ebfc96bec24effe3409f' (36)
>>> '.tag=0' (6)
>>> END-OF SENTENCE

<<< '/login' (6)
<<< '=name=admin' (11)
<<< '=response=0ce20d1ed4bd3ef821dc203a1ff2698461' (44)
<<< '.tag=1' (6)
<<< END-OF-SENTENCE

>>> '!done' (5)
>>> '.tag=1' (6)
>>> END-OF SENTENCE

<<< '/interface/monitor-traffic' (26)
<<< '=interface=ether1' (17)
<<< '=.proplist=rx-bits-per-second,tx-bits-per-second' (48)
<<< '.tag=2' (6)
<<< END-OF-SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=5744844' (26)
>>> 'tx-bits-per-second=61787' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"5744844", "tx-bits-per-second"=>"61787", ".tag"=>"2"}
>>> '!re' (3)
>>> 'rx-bits-per-second=4310298' (26)
>>> 'tx-bits-per-second=44242' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"4310298", "tx-bits-per-second"=>"44242", ".tag"=>"2"}
>>> '!re' (3)
>>> 'rx-bits-per-second=5442059' (26)
>>> 'tx-bits-per-second=63398' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"5442059", "tx-bits-per-second"=>"63398", ".tag"=>"2"}
>>> '!re' (3)
>>> 'rx-bits-per-second=5711572' (26)
>>> 'tx-bits-per-second=63509' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"5711572", "tx-bits-per-second"=>"63509", ".tag"=>"2"}
>>> '!re' (3)
>>> 'rx-bits-per-second=5711572' (26)
>>> 'tx-bits-per-second=63509' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"5711572", "tx-bits-per-second"=>"63509", ".tag"=>"2"}
>>> '!re' (3)
>>> 'rx-bits-per-second=3712135' (26)
>>> 'tx-bits-per-second=28404' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"3712135", "tx-bits-per-second"=>"28404", ".tag"=>"2"}
>>> '!re' (3)
>>> 'rx-bits-per-second=4822099' (26)
>>> 'tx-bits-per-second=39160' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"4822099", "tx-bits-per-second"=>"39160", ".tag"=>"2"}
>>> '!re' (3)
>>> 'rx-bits-per-second=4536317' (26)
>>> 'tx-bits-per-second=52562' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"4536317", "tx-bits-per-second"=>"52562", ".tag"=>"2"}
>>> '!re' (3)
>>> 'rx-bits-per-second=3976832' (26)
>>> 'tx-bits-per-second=45331' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"3976832", "tx-bits-per-second"=>"45331", ".tag"=>"2"}
>>> '!re' (3)
>>> 'rx-bits-per-second=4124776' (26)
>>> 'tx-bits-per-second=80547' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

{"!re"=>nil, "rx-bits-per-second"=>"4124776", "tx-bits-per-second"=>"80547", ".tag"=>"2"}
<<< '/cancel' (7)
<<< '=tag=2' (6)
<<< '.tag=3' (6)
<<< END-OF-SENTENCE

>>> '!trap' (5)
>>> 'category=2' (10)
>>> 'message=interrupted' (19)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!done' (5)
>>> '.tag=3' (6)
>>> END-OF SENTENCE

>>> '!done' (5)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

I suppose I should add an “auto-cancel after X replies” option to the MTik::command() method.

I hope this helps.

Aaron out.

you can use .tag for this, get number of replies you want and then cancel only the .tag

/cancel
=.tag=blah

only command with this tag will be cancelled.

I added the ability to auto-cancel a command after a specified number of replies to the Ruby mtik gem version 4.0.0. Using the new gem version, one could do this:

#!/usr/bin/env ruby

require 'rubygems'
require 'mtik'

# Be verbose in output
MTik::verbose = true

# Connect to the device:
p connection = MTik::command(
  :host    => '10.0.0.1',
  :user    => 'username',
  :pass    => 'password',
  :command => [
    "/interface/monitor-traffic",
    "=interface=ether0",
    "=.proplist=rx-bits-per-second,tx-bits-per-second"
  ],
  :limit => 10  ## Auto-cancel after 10 replies
)

And the output might look like this:

<<< '/login' (6)
<<< '.tag=0' (6)
<<< END-OF-SENTENCE

>>> '!done' (5)
>>> 'ret=2830ce30c78f9123d31544654d28a6e0' (36)
>>> '.tag=0' (6)
>>> END-OF SENTENCE

<<< '/login' (6)
<<< '=name=username' (9)
<<< '=response=008a9eba141f9e0f8d2337ab84366298cb' (44)
<<< '.tag=1' (6)
<<< END-OF-SENTENCE

>>> '!done' (5)
>>> '.tag=1' (6)
>>> END-OF SENTENCE

<<< '/interface/monitor-traffic' (26)
<<< '=interface=ether0' (21)
<<< '=.proplist=rx-bits-per-second,tx-bits-per-second' (48)
<<< '.tag=2' (6)
<<< END-OF-SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=326944' (25)
>>> 'tx-bits-per-second=1175812' (26)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=84251' (24)
>>> 'tx-bits-per-second=444610' (25)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=111604' (25)
>>> 'tx-bits-per-second=21782' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=116277' (25)
>>> 'tx-bits-per-second=681' (22)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=116277' (25)
>>> 'tx-bits-per-second=681' (22)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=339747' (25)
>>> 'tx-bits-per-second=14495' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=106012' (25)
>>> 'tx-bits-per-second=3952' (23)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=118867' (25)
>>> 'tx-bits-per-second=17370' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=130582' (25)
>>> 'tx-bits-per-second=29941' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!re' (3)
>>> 'rx-bits-per-second=130582' (25)
>>> 'tx-bits-per-second=29941' (24)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

<<< '/cancel' (7)
<<< '=tag=2' (6)
<<< '.tag=3' (6)
<<< END-OF-SENTENCE

>>> '!trap' (5)
>>> 'category=2' (10)
>>> 'message=interrupted' (19)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

>>> '!done' (5)
>>> '.tag=3' (6)
>>> END-OF SENTENCE

>>> '!done' (5)
>>> '.tag=2' (6)
>>> END-OF SENTENCE

<<< '/quit' (5)
<<< '.tag=4' (6)
<<< END-OF-SENTENCE

>>> '!fatal' (6)
>>> 'session terminated on request' (29)
>>> END-OF SENTENCE

[[{"!re"=>nil, "rx-bits-per-second"=>"326944", "tx-bits-per-second"=>"1175812", ".tag"=>"2"}, {"!re"=>nil, "rx-bits-per-second"=>"84251", "tx-bits-per-second"=>"444610", ".tag"=>"2"}, {"!re"=>nil, "rx-bits-per-second"=>"111604", "tx-bits-per-second"=>"21782", ".tag"=>"2"}, {"!re"=>nil, "rx-bits-per-second"=>"116277", "tx-bits-per-second"=>"681", ".tag"=>"2"}, {"!re"=>nil, "rx-bits-per-second"=>"116277", "tx-bits-per-second"=>"681", ".tag"=>"2"}, {"!re"=>nil, "rx-bits-per-second"=>"339747", "tx-bits-per-second"=>"14495", ".tag"=>"2"}, {"!re"=>nil, "rx-bits-per-second"=>"106012", "tx-bits-per-second"=>"3952", ".tag"=>"2"}, {"!re"=>nil, "rx-bits-per-second"=>"118867", "tx-bits-per-second"=>"17370", ".tag"=>"2"}, {"!re"=>nil, "rx-bits-per-second"=>"130582", "tx-bits-per-second"=>"29941", ".tag"=>"2"}, {"!re"=>nil, "rx-bits-per-second"=>"130582", "tx-bits-per-second"=>"29941", ".tag"=>"2"}, {"!trap"=>nil, "category"=>"2", "message"=>"interrupted", ".tag"=>"2"}, {"!done"=>nil, ".tag"=>"2"}]]

FYI, the Ruby MikroTik RouterOS API library always automatically tags all commands and automatically associates reply sentences with the command that generated the reply so that someone using the Ruby library can have multiple simultaneous commands executing over a single TCP API connection and not have to worry about manually tagging things.

Aaron out.