Related
I've been using ruamel yaml to edit my YAML files and dump them back. I need help understanding how to keep the same structure as the original file has, because all I do is duplicate it, edit, and write it again.
For example, this is the original file:
ElasticLoadBalancingV2Listener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
LoadBalancerArn: !Ref ElasticLoadBalancingV2LoadBalancer
Port: !FindInMap [NLBPorts, Port1, Port]
Protocol: "TCP"
DefaultActions:
-
Order: 1
TargetGroupArn: !Ref ElasticLoadBalancingV2TargetGroup1
Type: "forward"
The new file doesn't look the same:
ElasticLoadBalancingV2Listener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
LoadBalancerArn: !Ref ElasticLoadBalancingV2LoadBalancer
Port: !FindInMap [NLBPorts, Port1, Port]
Protocol: "TCP"
DefaultActions:
- Order: 1
TargetGroupArn: !Ref ElasticLoadBalancingV2TargetGroup1
Type: "forward"
The biggest issue is that I used all sorts of tricks that ruamel has to fix this, but each time some different part of the yaml breaks.
This is my function:
def editEndpointServiceTemplate(endpoint_service_template_path):
yaml = YAML()
yaml.preserve_quotes = True
# yaml.compact(seq_seq=False, seq_map=False)
# yaml.indent(mapping=4, sequence=3, offset=0)
#Load yaml file
with open(endpoint_service_template_path) as fp:
data = yaml.load(fp)
#Edit the yaml
data['Description'] = "CloudFormation"
#Write new yaml file
with open(endpoint_service_template_path, 'w') as fp:
yaml.dump(data, fp)
As you can see with the commented commands, I tinkered around with the settings but couldn't find the sweet spot.
In this case it is obvious that your function did not produce the output you present
(different indent, missing word "CloudFormation"), but in general you should take care
in questions this is the same, and that your program is complete so that results can
more easily be reproduced.
ruamel.yaml does not have built in functions for all kinds of seldom seen format, but yours
is relatively close to the output using the method .indent(mapping=4, sequence=4, offset=2) and
transform by checking line by line.
As it is less likely that withing string scalars you have a sequence indicators followed by three spaces ("- ")
(which additionally would have to occur wrapped to be the first non-space on a line), you better do
.indent(mapping=4, sequence=4, offset=0) transform that:
import sys
import ruamel.yaml
yaml_str = """\
ElasticLoadBalancingV2Listener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
LoadBalancerArn: !Ref ElasticLoadBalancingV2LoadBalancer
Port: !FindInMap [NLBPorts, Port1, Port]
Protocol: "TCP"
DefaultActions:
-
Order: 1
TargetGroupArn: !Ref ElasticLoadBalancingV2TargetGroup1
Type: "forward"
"""
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4, sequence=4, offset=0)
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
data['Description'] = "CloudFormation"
def break_seq(s):
result = []
PAT = '- '
for line in s.splitlines():
ls_line = line.lstrip()
if ls_line.startswith(PAT):
line = line.replace(PAT, ' - \n' + ' ' * (line.index(PAT) + 4))
result.append(line)
return '\n'.join(result)
yaml.dump(data, sys.stdout, transform=break_seq)
which gives:
ElasticLoadBalancingV2Listener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
LoadBalancerArn: !Ref ElasticLoadBalancingV2LoadBalancer
Port: !FindInMap [NLBPorts, Port1, Port]
Protocol: "TCP"
DefaultActions:
-
Order: 1
TargetGroupArn: !Ref ElasticLoadBalancingV2TargetGroup1
Type: "forward"
Description: CloudFormation
The above can be done by "hacking" the routines that serialize to sequences, but
it is often easier to just transform the output, although not as efficient in
time/space usage.
Unless the program consuming this output uses an incomplete YAML parser, the
actual data structure loaded will not change, it is just less readable for people
unused to such uncommon formatting.
I am new on the XMPP server ejabberd. I installed ejabberd on ubuntu from this link: https://docs.ejabberd.im/admin/installation/#install-on-linux. I am using the default ejabberd.yml file which is present in ejabberd-20.07/conf folder. Here is my ejabberd.yml file:
hosts:
- "faiqkhan-VirtualBox"
loglevel: 4
log_rotate_size: 10485760
log_rotate_count: 1
certfiles:
- "/home/faiqkhan/ejabberd-20.07/conf/server.pem"
## - "/etc/letsencrypt/live/localhost/fullchain.pem"
## - "/etc/letsencrypt/live/localhost/privkey.pem"
ca_file: "/home/faiqkhan/ejabberd-20.07/conf/cacert.pem"
listen:
-
port: 5222
ip: "::"
module: ejabberd_c2s
max_stanza_size: 262144
shaper: c2s_shaper
access: c2s
starttls_required: false
-
port: 5269
ip: "::"
module: ejabberd_s2s_in
max_stanza_size: 524288
-
port: 5443
ip: "::"
module: ejabberd_http
tls: true
request_handlers:
"/admin": ejabberd_web_admin
"/api": mod_http_api
"/bosh": mod_bosh
"/captcha": ejabberd_captcha
"/upload": mod_http_upload
"/ws": ejabberd_http_ws
"/oauth": ejabberd_oauth
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
"/admin": ejabberd_web_admin
-
port: 1883
ip: "::"
module: mod_mqtt
backlog: 1000
s2s_use_starttls: optional
acl:
local:
user_regexp: ""
loopback:
ip:
- 127.0.0.0/8
- ::1/128
- ::FFFF:127.0.0.1/128
admin:
user:
- "admin#faiqkhan-VirtualBox"
access_rules:
local:
allow: local
c2s:
deny: blocked
allow: all
announce:
allow: admin
configure:
allow: admin
muc_create:
allow: local
pubsub_createnode:
allow: local
trusted_network:
allow: local
api_permissions:
"console commands":
from:
- ejabberd_ctl
who: all
what: "*"
"admin access":
who:
access:
allow:
acl: loopback
acl: admin
oauth:
scope: "ejabberd:admin"
access:
allow:
acl: loopback
acl: admin
what:
- "*"
- "!stop"
- "!start"
"public commands":
who:
ip: 127.0.0.1/8
what:
- status
- connected_users_number
shaper:
normal: 1000
fast: 50000
shaper_rules:
max_user_sessions: 10
max_user_offline_messages:
5000: admin
100: all
c2s_shaper:
none: admin
normal: all
s2s_shaper: fast
max_fsm_queue: 10000
acme:
contact: "mailto:admin#faiqkhan-VirtualBox"
ca_url: "https://acme-v02.api.letsencrypt.org/directory"
modules:
mod_adhoc: {}
mod_admin_extra: {}
mod_announce:
access: announce
mod_avatar: {}
mod_blocking: {}
mod_bosh: {}
mod_caps: {}
mod_carboncopy: {}
mod_client_state: {}
mod_configure: {}
mod_disco: {}
mod_fail2ban: {}
mod_http_api: {}
mod_http_upload:
put_url: https://#HOST#:5443/upload
mod_last: {}
mod_mam:
## Mnesia is limited to 2GB, better to use an SQL backend
## For small servers SQLite is a good fit and is very easy
## to configure. Uncomment this when you have SQL configured:
## db_type: sql
assume_mam_usage: true
default: never
mod_mqtt: {}
mod_muc:
access:
- allow
access_admin:
- allow: admin
access_create: muc_create
access_persistent: muc_create
access_mam:
- allow
default_room_options:
allow_subscription: true # enable MucSub
mam: false
mod_muc_admin: {}
mod_offline:
access_max_user_messages: max_user_offline_messages
mod_ping: {}
mod_privacy: {}
mod_private: {}
mod_proxy65:
access: local
max_connections: 5
mod_pubsub:
access_createnode: pubsub_createnode
plugins:
- flat
- pep
force_node_config:
## Avoid buggy clients to make their bookmarks public
storage:bookmarks:
access_model: whitelist
mod_push: {}
mod_push_keepalive: {}
mod_register:
## Only accept registration requests from the "trusted"
## network (see access_rules section above).
## Think twice before enabling registration from any
## address. See the Jabber SPAM Manifesto for details:
## https://github.com/ge0rg/jabber-spam-fighting-manifesto
ip_access: all
mod_roster:
versioning: true
mod_s2s_dialback: {}
mod_shared_roster: {}
mod_stream_mgmt:
resend_on_timeout: if_offline
mod_vcard: {}
mod_vcard_xupdate: {}
mod_version:
show_os: false
mod_stanza_ack: {}
I try the given code in the link question Ejabberd return message to sender hook / message receipts and added my module in ejabberd.yml file which is in the last line of the above code. I create mod_stanza_ack.erl file and compile the file using command
./erlc mod_stanza_ack.erl
and get mod_stanza_ack.beam file. I coped mod_stanza_ack.beam file to ejabberd-20.07/lib/ejabberd-20.07/ebin folder where all the module files are present. Then I start ejabberd server using
./ejabberdctl live
command to view logs. Module works for me but on the server-side, it always crashes with an error
**Hook user_send_packet crashed when running mod_stanza_ack:on_user_send_packet/1:
** exception error: undefined function mod_stanza_ack:on_user_send_packet/1
in function ejabberd_hooks:safe_apply/4 (src/ejabberd_hooks.erl, line 236)
in call from ejabberd_hooks:run_fold1/4 (src/ejabberd_hooks.erl, line 217)
in call from ejabberd_c2s:handle_authenticated_packet/2 (src/ejabberd_c2s.erl, line 484)
in call from xmpp_stream_in:process_authenticated_packet/2 (src/xmpp_stream_in.erl, line 714)
in call from xmpp_stream_in:handle_info/2 (src/xmpp_stream_in.erl, line 404)
in call from p1_server:handle_msg/8 (src/p1_server.erl, line 696)
in call from proc_lib:init_p_do_apply/3 (proc_lib.erl, line 249)**.
Did I miss something? Or using deprecated functions?
Well, that example source code is six years old, and ejabberd development API has changed since then. I've updated the example, and this compiles and starts correctly with ejabberd 20.07:
-module(mod_stanza_ack).
-behaviour(gen_mod).
-include("xmpp.hrl").
-include("logger.hrl").
-include("translate.hrl").
-export([start/2, stop/1, mod_options/1, mod_doc/0, depends/2]).
-export([on_user_send_packet/1]).
start(Host, _Opts) ->
?INFO_MSG("mod_stanza_ack starting", []),
ejabberd_hooks:add(user_send_packet, Host, ?MODULE, on_user_send_packet, 0),
ok.
stop(Host) ->
?INFO_MSG("mod_stanza_ack stopping", []),
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, on_user_send_packet, 0),
ok.
on_user_send_packet({#presence{to = To, from = From} = Packet, C2SState}) ->
?INFO_MSG("mod_stanza_ack a presence has been sent coming from: ~p", [From]),
?INFO_MSG("mod_stanza_ack a presence has been sent to: ~p", [To]),
?INFO_MSG("mod_stanza_ack a presence has been sent with the following packet:~n ~p", [Packet]),
{Packet, C2SState};
on_user_send_packet({#iq{to = To, from = From} = Packet, C2SState}) ->
?INFO_MSG("mod_stanza_ack a iq has been sent coming from: ~p", [From]),
?INFO_MSG("mod_stanza_ack a iq has been sent to: ~p", [To]),
?INFO_MSG("mod_stanza_ack a iq has been sent with the following packet:~n ~p", [Packet]),
{Packet, C2SState};
on_user_send_packet({#message{to = To, from = From} = Packet, C2SState}) ->
?INFO_MSG("mod_stanza_ack a message has been sent coming from: ~p", [From]),
?INFO_MSG("mod_stanza_ack a message has been sent to: ~p", [To]),
?INFO_MSG("mod_stanza_ack a message has been sent with the following packet:~n ~p", [Packet]),
{Packet, C2SState}.
depends(_Host, _Opts) ->
[].
mod_options(_Host) ->
[].
mod_doc() ->
#{desc =>
?T("This an example module.")}.
Following your detailed step by step installation guide, I get two problems, that I describe here and how to solve them:
Compilation lacks header files.
I copy mod_stanza_ack.erl to ejabberd-20.07/bin, and then run this command:
$ ./erlc mod_stanza_ack.erl
mod_stanza_ack.erl:4: can't find include file "xmpp.hrl"
mod_stanza_ack.erl:5: can't find include file "logger.hrl"
mod_stanza_ack.erl:6: can't find include file "translate.hrl"
mod_stanza_ack.erl:12: undefined macro 'INFO_MSG/2'
mod_stanza_ack.erl:17: undefined macro 'INFO_MSG/2'
mod_stanza_ack.erl:22: undefined macro 'INFO_MSG/2'
mod_stanza_ack.erl:47: undefined macro 'T/1'
mod_stanza_ack.erl:8: function mod_doc/0 undefined
mod_stanza_ack.erl:8: function start/2 undefined
mod_stanza_ack.erl:8: function stop/1 undefined
mod_stanza_ack.erl:9: function on_user_send_packet/1 undefined
The solution is simple: provide the paths to the header files:
$ ./erlc -I ../lib/ejabberd-20.07/include/ -I ../lib/xmpp-1.4.9/include/ -I ../lib/fast_xml-1.1.43/include/ mod_stanza_ack.erl
This way the file is compiled correctly.
INFO_MSG in the source code do not produce log messages in ejabberd log file or "ejabberdctl live" console.
This is because we didn't tell the compiler to use the LAGER library. The solution is quite simple: include -DLAGER in the module compilation. So, this is the perfect compilation call:
$ ./erlc -I ../lib/ejabberd-20.07/include/ -I ../lib/xmpp-1.4.9/include/ -I ../lib/fast_xml-1.1.43/include/ -DLAGER mod_stanza_ack.erl
Now, you copy the resulting mod_stanza_ack.beam with all the other ejabberd beam files, enable the module in ejabberd.yml, and restart ejabberd, and all will work as expected
my config is follow:
preprocessor sfportscan: proto { all } \
scan_type { all } \
sense_level { high } \
logfile { alert }
when I run snort,and use nmap to scan,then log file output as follow:
Time: 02/23-12:54:21.183932
event_ref: 0
[Source ip address] -> [Destination ip address] (portscan) TCP Portscan
Priority Count: 9
Connection Count: 10
IP Count: 1
Scanner IP Range: [Destination ip address]:[Destination ip address]
Port/Proto Count: 10
Port/Proto Range: 981:12174
but the snort doc say as this:
Time: 09/08-15:07:31.603880
event_id: 2
192.168.169.3 -> 192.168.169.5 (portscan) TCP Filtered Portscan
Priority Count: 0
Connection Count: 200
IP Count: 2
Scanner IP Range: 192.168.169.3:192.168.169.4
Port/Proto Count: 200
Port/Proto Range: 20:47557
If there are open ports on the target, one or more additional tagged packet(s) will be appended:
Time: 09/08-15:07:31.603881
event_ref: 2
192.168.169.3 -> 192.168.169.5 (portscan) Open Port
Open Port: 38458
I do not has event_id,instead is event_ref and its value is 0
I'm trying to use gstreamer at odroid C1+.
I installed gstreamer, base, good, ugly, bad, libav getting from here
https://gstreamer.freedesktop.org/modules/
following here
http://linuxfromscratch.org/blfs/view/svn/index.html
But when I run like this
gst-launch-1.0 -e pulsesrc device="alsa_input.usb-046d_0809_52A63768-02.analog-mono" ! audioconvert ! lamemp3enc target=1 bitrate=64 cbr=true ! filesink location=audio.mp3
I get error
WARNING: erroneous pipeline: no element "lamemp3enc"
How should I do?
++
I run
GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/ gst-inspect-1.0 lamemp3enc
and get
Factory Details:
Rank primary (256)
Long-name L.A.M.E. mp3 encoder
Klass Codec/Encoder/Audio
Description High-quality free MP3 encoder
Author Sebastian Dröge <sebastian.droege#collabora.co.uk>
Plugin Details:
Name lame
Description Encode MP3s with LAME
Filename /usr/lib/gstreamer-1.0/libgstlame.so
Version 1.8.1
License LGPL
Source module gst-plugins-ugly
Source release date 2016-04-20
Binary package GStreamer Ugly Plugins 1.8.1 BLFS
Origin URL http://www.linuxfromscratch.org/blfs/view/svn/
GObject
+----GInitiallyUnowned
+----GstObject
+----GstElement
+----GstAudioEncoder
+----GstLameMP3Enc
Implemented Interfaces:
GstPreset
Pad Templates:
SINK template: 'sink'
Availability: Always
Capabilities:
audio/x-raw
format: S16LE
layout: interleaved
rate: { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }
channels: 1
audio/x-raw
format: S16LE
layout: interleaved
rate: { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }
channels: 2
channel-mask: 0x0000000000000003
SRC template: 'src'
Availability: Always
Capabilities:
audio/mpeg
mpegversion: 1
layer: 3
rate: { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }
channels: [ 1, 2 ]
Element Flags:
no flags set
Element Implementation:
Has change_state() function: gst_audio_encoder_change_state
Element has no clocking capabilities.
Element has no URI handling capabilities.
Pads:
SINK: 'sink'
Pad Template: 'sink'
SRC: 'src'
Pad Template: 'src'
Element Properties:
name : The name of the object
flags: readable, writable
String. Default: "lamemp3enc0"
parent : The parent of the object
flags: readable, writable
Object of type "GstObject"
perfect-timestamp : Favour perfect timestamps over tracking upstream timestamps
flags: readable, writable
Boolean. Default: false
mark-granule : Apply granule semantics to buffer metadata (implies perfect-timestamp)
flags: readable
Boolean. Default: false
hard-resync : Perform clipping and sample flushing upon discontinuity
flags: readable, writable
Boolean. Default: false
tolerance : Consider discontinuity if timestamp jitter/imperfection exceeds tolerance (ns)
flags: readable, writable
Integer64. Range: 0 - 9223372036854775807 Default: 40000000
target : Optimize for quality or bitrate
flags: readable, writable
Enum "GstLameMP3EncTarget" Default: 0, "quality"
(0): quality - Quality
(1): bitrate - Bitrate
bitrate : Bitrate in kbit/sec (Only valid if target is bitrate, for CBR one of 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256 or 320)
flags: readable, writable
Integer. Range: 8 - 320 Default: 128
cbr : Enforce constant bitrate encoding (Only valid if target is bitrate)
flags: readable, writable
Boolean. Default: false
quality : VBR Quality from 0 to 10, 0 being the best (Only valid if target is quality)
flags: readable, writable
Float. Range: 0 - 9.999 Default: 4
encoding-engine-quality: Quality/speed of the encoding engine, this does not affect the bitrate!
flags: readable, writable
Enum "GstLameMP3EncEncodingEngineQuality" Default: 1, "standard"
(0): fast - Fast
(1): standard - Standard
(2): high - High
mono : Enforce mono encoding
flags: readable, writable
Boolean. Default: false
Presets:
"Ubuntu"
what OS are you running on odroid (Android/Ubuntu?) what gives gst-inspect-1.0 lamemp3enc.. there is library path .. you can ldd it:
ldd /usr/local/lib/gstreamer-1.0/libgstlame.so
linux-vdso.so.1 => (0x00007ffc7dbed000)
libgstaudio-1.0.so.0 => /usr/local/lib/libgstaudio-1.0.so.0 (0x00007f4a97faa000)
libgstbase-1.0.so.0 => /usr/local/lib/libgstbase-1.0.so.0 (0x00007f4a97d4c000)
libgstreamer-1.0.so.0 => /usr/local/lib/libgstreamer-1.0.so.0 (0x00007f4a97a31000)
libgobject-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f4a977e0000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f4a974d8000)
libmp3lame.so.0 => /usr/lib/x86_64-linux-gnu/libmp3lame.so.0 (0x00007f4a9724a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4a9702c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4a96c67000)
libgsttag-1.0.so.0 => /usr/local/lib/libgsttag-1.0.so.0 (0x00007f4a96a2d000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4a96727000)
liborc-0.4.so.0 => /usr/local/lib/liborc-0.4.so.0 (0x00007f4a964a4000)
libgmodule-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f4a9629f000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f4a96097000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4a95e93000)
libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f4a95c8a000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f4a95a4c000)
/lib64/ld-linux-x86-64.so.2 (0x0000558c95a32000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f4a95833000)
Check if you have all libs .. you need especially libmp3lame.so ..
You can always use apt-file tool to check which package provides this lib.. but its quite apparent that its this package (run as root or sudo):
apt-get install libmp3lame-dev
If you did not have it at compile time (I guess you compiled as you linked linuxfromscratch..) you need to recomiple gst-plugins-ugly after installing this lib..
Then check the last part at when you rerun configure at ugly (I would suggest using autogen.sh instead.. but I dont know your environment..) which should mention if you will have mp3 builded..
UPDATE
So you just need to set the env variable GST_PLUGIN_PATH. Gstreamer just haven't known where to look for the gstreamer mp3 plugin..
you can export the env variable.. say in ~/.basrhc:
export GST_PLUGIN_PATH=/usr/lib/gstreamer-1.0/
and then just the same pipe will work perfectly, this is simpler one (tested, works):
gst-launch-1.0 -e audiotestsrc ! audioconvert ! lamemp3enc ! filesink location=audio.mp3
HTH
I'm new on perl and still learning by doing some case. I've some case on parsing a log with perl.
There is a data log :
Physical interface: ge-1/0/2, Unit: 101, Vlan-id: 101, Address: 10.187.132.3/27
Index: 353, SNMP ifIndex: 577, VRRP-Traps: enabled
Interface state: up, Group: 1, State: backup, VRRP Mode: Active
Priority: 190, Advertisement interval: 1, Authentication type: none
Advertisement threshold: 3, Delay threshold: 100, Computed send rate: 0
Preempt: yes, Accept-data mode: yes, VIP count: 1, VIP: 10.187.132.1
Dead timer: 2.715s, Master priority: 200, Master router: 10.187.132.2
Virtual router uptime: 5w5d 12:54
Tracking: disabled
Physical interface: ge-1/0/2, Unit: 102, Vlan-id: 102, Address: 10.187.132.35/27
Index: 354, SNMP ifIndex: 580, VRRP-Traps: enabled
Interface state: up, Group: 2, State: master, VRRP Mode: Active
Priority: 200, Advertisement interval: 1, Authentication type: none
Advertisement threshold: 3, Delay threshold: 100, Computed send rate: 0
Preempt: yes, Accept-data mode: yes, VIP count: 1, VIP: 10.187.132.33
Advertisement Timer: 0.816s, Master router: 10.187.132.35
Virtual router uptime: 5w5d 12:54, Master router uptime: 5w5d 12:54
Virtual Mac: 00:00:5e:00:01:02
Tracking: disabled
Physical interface: ge-1/0/2, Unit: 103, Vlan-id: 103, Address: 10.187.132.67/27
Index: 355, SNMP ifIndex: 581, VRRP-Traps: enabled
Interface state: up, Group: 3, State: backup, VRRP Mode: Active
Priority: 190, Advertisement interval: 1, Authentication type: none
Advertisement threshold: 3, Delay threshold: 100, Computed send rate: 0
Preempt: yes, Accept-data mode: yes, VIP count: 1, VIP: 10.187.132.65
Dead timer: 2.624s, Master priority: 200, Master router: 10.187.132.66
Virtual router uptime: 5w5d 12:54
Tracking: disabled
I curious how we can retrieve some value and store it to array. I've tried grep it but I'm confuse how to take a spesific value.
Expected Value on Array of Hashes:
$VAR1 = {
'interface' => 'ge-1/0/2.101',
'address' => '10.187.132.3/27',
'State' => 'backup'
'Master-router' => '10.187.132.2'
};
$VAR2 = {
'interface' => 'ge-1/0/2.102',
'address' => '10.187.132.35/27',
'State' => 'master'
'Master-router' => '10.187.132.35'
};
$VAR3 = {
'interface' => 'ge-1/0/2.103',
'address' => '10.187.132.67/27',
'State' => 'backup'
'Master-router' => '10.187.132.66'
};
You could use regex to split each paragraph up. Something like this might work:
/((\w|\s|-)+):\s([^,]+)/m
The matching groups would then look something like:
Match 1
1. Physical interface
2. e
3. ge-1/0/2
Match 2
1. Unit
2. t
3. 101
Match 3
1. Vlan-id
2. d
3. 101
As you can see 1. corresponds to a key whereas 3. is the corresponding value. You can store the set of pairs any way you like.
For this to work each attribute in the log would need to be comma-seperated, which the example you have listed isn't. Assuming the example you have listed is correct, you would have to adjust the regex a little to make it work. You can test it online at rubular until it works. If it is comma seperated you might just want to split each paragraph by "," and then split each result on ":".
EDIT:
It seems to me like each line is comma seperated so the methods mentioned above might work perfectly well if you use them on a single line at a time.
To parse the data:
Obtain a section from the file by reading lines into a section while the lines start with whitespace.
Split the sections at the item separators which are either commas or linebreaks
Split each item at the first colon into a key and value
Case-fold the key and store the pair into a hash
A sketch of an implementation:
my #hashes;
while (<>) {
push #hashes, {} if /\A\S/;
for my $item (split /,/) {
my ($k, $v) = split /:/, $item, 2;
$hashes[-1]{fc $k} = $v;
}
}
Then you can extract those pieces of information from the hash which you are interested in.
Since each record is a paragraph, you can have Perl read the file in those chunks by local $/ = ''; (paragraph mode). Then, use a regex to capture each value that you want within that paragraph, pair that value with a hash key, and then push a reference to that hash onto an array to form an array of hashes (AoH):
use strict;
use warnings;
use Data::Dumper;
my #arr;
local $/ = '';
while (<DATA>) {
my %hash;
( $hash{'interface'} ) = /interface:\s+([^,]+)/;
( $hash{'address'} ) = /Address:\s+(\S+)/;
( $hash{'State'} ) = /State:\s+([^,]+)/;
( $hash{'Master-router'} ) = /Master router:\s+(\S+)/;
push #arr, \%hash;
}
print Dumper \#arr;
__DATA__
Physical interface: ge-1/0/2, Unit: 101, Vlan-id: 101, Address: 10.187.132.3/27
Index: 353, SNMP ifIndex: 577, VRRP-Traps: enabled
Interface state: up, Group: 1, State: backup, VRRP Mode: Active
Priority: 190, Advertisement interval: 1, Authentication type: none
Advertisement threshold: 3, Delay threshold: 100, Computed send rate: 0
Preempt: yes, Accept-data mode: yes, VIP count: 1, VIP: 10.187.132.1
Dead timer: 2.715s, Master priority: 200, Master router: 10.187.132.2
Virtual router uptime: 5w5d 12:54
Tracking: disabled
Physical interface: ge-1/0/2, Unit: 102, Vlan-id: 102, Address: 10.187.132.35/27
Index: 354, SNMP ifIndex: 580, VRRP-Traps: enabled
Interface state: up, Group: 2, State: master, VRRP Mode: Active
Priority: 200, Advertisement interval: 1, Authentication type: none
Advertisement threshold: 3, Delay threshold: 100, Computed send rate: 0
Preempt: yes, Accept-data mode: yes, VIP count: 1, VIP: 10.187.132.33
Advertisement Timer: 0.816s, Master router: 10.187.132.35
Virtual router uptime: 5w5d 12:54, Master router uptime: 5w5d 12:54
Virtual Mac: 00:00:5e:00:01:02
Tracking: disabled
Physical interface: ge-1/0/2, Unit: 103, Vlan-id: 103, Address: 10.187.132.67/27
Index: 355, SNMP ifIndex: 581, VRRP-Traps: enabled
Interface state: up, Group: 3, State: backup, VRRP Mode: Active
Priority: 190, Advertisement interval: 1, Authentication type: none
Advertisement threshold: 3, Delay threshold: 100, Computed send rate: 0
Preempt: yes, Accept-data mode: yes, VIP count: 1, VIP: 10.187.132.65
Dead timer: 2.624s, Master priority: 200, Master router: 10.187.132.66
Virtual router uptime: 5w5d 12:54
Tracking: disabled
Output:
$VAR1 = [
{
'Master-router' => '10.187.132.2',
'interface' => 'ge-1/0/2',
'address' => '10.187.132.3/27',
'State' => 'backup'
},
{
'Master-router' => '10.187.132.35',
'interface' => 'ge-1/0/2',
'address' => '10.187.132.35/27',
'State' => 'master'
},
{
'Master-router' => '10.187.132.66',
'interface' => 'ge-1/0/2',
'address' => '10.187.132.67/27',
'State' => 'backup'
}
];
Hope this helps!