рд╕рдВрднрд╛рд╡рд┐рдд рдирд┐рдЧрд░рд╛рдиреА, тАЛтАЛрд╕рдВрднрд╛рд╡рд┐рдд рд╡рд┐рдлрд▓рддрд╛ рдЕрд▓рд░реНрдЯ


рдпрд╣ рдкреЛрд╕реНрдЯ рдкрд┐рдЫрд▓реЗ рдПрдХ рдХреА рдирд┐рд░рдВрддрд░рддрд╛ рд╣реИред рдкреВрд░реНрд╡рд╛рдиреБрдорд╛рди рдирд┐рдЧрд░рд╛рдиреА рдПрдХ рдорд╛рдирдХ рдирд┐рдЧрд░рд╛рдиреА рд╡рд┐рдзрд┐ рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╕реВрдЪрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд╛рдлреА рдорд╛рдирдХ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдмрд┐рд▓реНрдХреБрд▓ рдХреНрдпреЛрдВред

рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди рдХреНрдпрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП


рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рд░ рдХреЛрдИ рджрд┐рд▓рдЪрд╕реНрдкреА рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рдХреМрди рдЕрдкрдиреЗ рджреИрдирд┐рдХ рдХрд╛рд░реНрдп рдореЗрдВ рдХрд┐рд╕ рдирд┐рдЧрд░рд╛рдиреА рдкреНрд░рдгрд╛рд▓реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рд╣рдо, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рд╣рдордиреЗ рдЙрд╕реЗ рд╕рд┐рдЦрд╛рдпрд╛ рдХрд┐ рд╕рдВрдкреВрд░реНрдг рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХреИрд╕реЗ рдХреА рдЬрд╛рдП, рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ - рд╡реАрдУрдЖрдИрдкреА рдХреЛ рдкрд╛рд░ рдХрд░рдирд╛ред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рджреЛрд╕реНрдд рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЪрд▓рдиреЗ рдкрд░ рдореЗрд▓ рдФрд░ рдкреЙрдкрдЕрдк рджреНрд╡рд╛рд░рд╛ рдЕрд▓рд░реНрдЯ рдХреИрд╕реЗ рджрд┐рдпрд╛ рдЬрд╛рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдордиреЗ рдЙрд╕реЗ рдПрдХ рдмрд╛рд╣рд░реА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕рд╛рде рдПрд╕рдПрдордПрд╕ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд┐рдЦрд╛рдпрд╛ред рд▓реЗрдХрд┐рди рдпрд╣ рдЙрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИред
рдЬрдм рдореЙрдирд┐рдЯрд░рд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рд╕реЗ рдХреЛрдИ рдЕрд▓рд░реНрдЯ рдЖрддрд╛ рд╣реИ, рддреЛ рдЕрд▓рд░реНрдЯ рдХреЛ рд╕реНрд╡рдпрдВ рдЗрдВрдЧрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдХрд┐рди рдиреЛрдбреНрд╕ рдореЗрдВ рд╡рд┐рдлрд▓рддрд╛ рд╣реБрдИ рдереА, рдФрд░ рдореВрд▓реНрдп рдХреЗ рдЕрдВрддрд┐рдо рдорд╛рдк рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХреА рдЬрд╛ рд░рд╣реА рдереАред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рд╕реВрдЪрдирд╛ рдкреНрд░рд╛рдкреНрдд рд╣реЛ рд╕рдХрддреА рд╣реИ рдХрд┐ Router1 рдкрд░ рдкреНрд░реЛрд╕реЗрд╕рд░ 95 рдкреНрд░рддрд┐рд╢рдд рднрд░рд╛ рд╣реБрдЖ рд╣реИред рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдХреА рдЪреЗрддрд╛рд╡рдиреА рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдЗрд╕рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдХреА рдХрд┐рддрдиреА рдЬрд▓реНрджреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдПрдХ рдФрд░ рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЬрдм рдЖрдк рдкреВрд░реНрд╡рд╛рдиреБрдорд╛рди рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд╣рдЬрд╛рд░реЛрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВред
рд╣рд╛рдВ, рдЖрдк рдПрдХ рдЪреЗрддрд╛рд╡рдиреА рдореЗрдВ рдЕрдВрддрд┐рдо рдорд╛рдк рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЖрдк рдХрдИ рд╣рд╛рд▓рд┐рдпрд╛ рдорд╛рдкреЛрдВ рдХреЗ рдФрд╕рдд рдкрд░рд┐рдгрд╛рдо рдпрд╛ рдорд╛рдк рдореВрд▓реНрдп рднреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдПрдХ рджрд┐рди рдкрд╣рд▓реЗ рдерд╛ред рд▓реЗрдХрд┐рди рдпрд╣ рдЕрдХреНрд╕рд░ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рдмрд╕реЗ рдкреНрд░рднрд╛рд╡реА рдЕрдзрд┐рд╕реВрдЪрдирд╛ рд╡рд┐рдзрд┐ рдЕрдзрд┐рд╕реВрдЪрдирд╛ рд╣реИ, рдЬреЛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЕрд╡рдзрд┐ рдХреЗ рд▓рд┐рдП рдорд╛рдкрд╛ рдореВрд▓реНрдп рдХрд╛ рдЧреНрд░рд╛рдл рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреА рд╣реИред рдЪрд╛рд░реНрдЯ рдкрд░ рдПрдХ рд╕рд░рд▓ рдирдЬрд╝рд░ рдпрд╣ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╕рдВрднрд╛рд╡рд┐рдд рд╡рд┐рдлрд▓рддрд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рдФрд░ рдХреНрдпрд╛ рд╡рд┐рдлрд▓рддрд╛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣реБрдИ рд╣реИ, рдпрд╛ рдХреНрдпрд╛ рдпрд╣ рдПрдХ рдЭреВрдареА рд╕рдХрд╛рд░рд╛рддреНрдордХ рд╣реИред

Rrdtool рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдг


рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдкрд┐рдЫрд▓реЗ рдкреЛрд╕реНрдЯреЛрдВ рдореЗрдВ рд▓рд┐рдЦрд╛ рдерд╛, rrdtool рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╛рд╡рд┐рдд рд╡рд┐рдлрд▓рддрд╛рдУрдВ рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХрд░рдиреЗ рдФрд░ рдкрд╣рдЪрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП - aberrations, рдЖрдкрдХреЛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ rrd рдбреЗрдЯрд╛рдмреЗрд╕ рдмрдирд╛рдиреЗ рдФрд░ рдмрд╕ рдЗрд╕реЗ рд╡рд░реНрддрдорд╛рди рдорд╛рдиреЛрдВ рд╕реЗ рднрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд╕рд╛рде, рдорд╛рдкрд╛ рдореВрд▓реНрдп рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдзрд╛рд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдФрд░ рдореВрд▓реНрдп - рд╡рд┐рдлрд▓рддрд╛рдУрдВ рд╕реЗ рднрд░рд╛ рд╣реЛрддрд╛ рд╣реИред FAILURES рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╣реИрд╢ рд╣реИ рдЬрд┐рд╕рдХрд╛ рд╕реВрдЪрдХрд╛рдВрдХ рд╕рдордп (рдпреВрдирд┐рдХреНрд╕рдЯрд╛рдЗрдо) рд╣реИ рдЬрд┐рд╕ рдкрд░ рдорд╛рдк рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд╕реВрдЪрдХрд╛рдВрдХ рдореВрд▓реНрдп рдорд╛рдкрд╛ рдореВрд▓реНрдп рд╡рд┐рдкрдерди рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрддреЗ рд╣реИрдВред рдпрд╣ рд╕рд░рд▓ рд╣реИ, рдПрдХ рд╡рд┐рдкрдерди рдерд╛, FAILURES рдХрд╛ рдореВрд▓реНрдп 1 рд╣реИ, рд╡рд╣рд╛рдБ - 0 рдирд╣реАрдВ рдерд╛ред
рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЕрдВрддрд┐рдо рдорд╛рдк рдХреЗ рдмрд╛рдж рдХреЗрд╡рд▓ рдлреАрд▓реНтАНрд╕ рдорд╛рди рдХреА рдЬрд╛рдБрдЪ рдХрд░рдирд╛ рдХрд╛рдлреА рдирд╣реАрдВ рд╣реИред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рд╡рд┐рдкрдерди рдХрд╛рдлреА рд▓рдВрдмреЗ рд╕рдордп рддрдХ рд░рд╣ рд╕рдХрддрд╛ рд╣реИ, рдЧреНрд░рд╛рдл рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред

рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ, рдирд┐рдЧрд░рд╛рдиреА рдкреНрд░рдгрд╛рд▓реА рдХреЛ рдореВрд▓реНрдп рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдорд╛рдк рдХреЗ рдмрд╛рдж рдЪреЗрддрд╛рд╡рдиреА рдирд╣реАрдВ рджреЗрдиреА рдЪрд╛рд╣рд┐рдП рдЬрдмрдХрд┐ рд╡рд┐рдкрдерди рдореМрдЬреВрдж рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдпрд╣ рднреА рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЕрдЧрд░ рдЙрдиреНрдореВрд▓рди рдЦрддреНрдо рд╣реЛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдареАрдХ рд╣реЛ рдЧрдИ рд╣реИ, рдРрд╕рд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╕рд┐рд╕реНрдЯрдо рдХреЗрд╡рд▓ рдирдП рдореВрд▓реНрдпреЛрдВ рдХреЗ рдкреВрд░реНрд╡рд╛рдиреБрдорд╛рди рдХреЛ рд╕рдорд╛рдпреЛрдЬрд┐рдд рдХрд░рддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЙрджрд╛рд╣рд░рдг рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЖрдВрдХрдбрд╝реЗ рдореЗрдВ рд╣реИ, рдзрд╛рд░рд╛ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛ рд╣рд▓ рдирд╣реАрдВ рд╣реБрдИ рд╣реИ, рдФрд░ рд╡рд┐рдкрдерди рдкрд╣рд▓реЗ рд╣реА рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдпрд╛ рд╣реИред

рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддреЗ рд╕рдордп рд╕рдмрд╕реЗ рд╕рд╣реА рдЖрдИрдПрдордПрдЪрдУ рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рд╣реИ рдХрд┐ рдЬрдм рдпрд╣ рд╢реБрд░реВ рд╣реБрдЖ рдФрд░ рдХрдм рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдпрд╛, рдЗрд╕ рд╕рдордп рдПрдХ рд╢реЗрдбреНрдпреВрд▓ рдХреЗ рд╕рд╛рде рдЕрд▓рд░реНрдЯ рднреЗрдЬрдирд╛ рд╣реИред

рдпрд╣ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ


рджрд░рдЕрд╕рд▓, рд╕реНрдХреНрд░рд┐рдкреНрдЯ:
#!/usr/bin/env python import os import time import rrdtool import tempfile import smtplib from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart COMMASPACE = ', ' # Define params rrdpath = '/usr/rrdmonit/rrd/' pngpath = '/usr/local/share/cacti/rrdmonit/ width = '500' height = '200' mailsender = "alerter@my-domain.com" mailreceip = ["admins@my-domain.com", "support@my-domain.com"] mailserver = 'mx.my-domain.com' # Generate charts for last 48 hours enddate = int(time.mktime(time.localtime())) begdate = enddate - 172800 def send_alert_attached(subject, flist): """ Will send e-mail, attaching png files in the flist. """ msg = MIMEMultipart() msg['Subject'] = subject msg['From'] = mailsender msg['To'] = COMMASPACE.join(mailreceip) for file in flist: png_file = pngpath+file.split('.')[0]+'.png' print png_file fp = open(png_file, 'rb') img = MIMEImage(fp.read()) fp.close() msg.attach(img) mserver = smtplib.SMTP(mailserver) mserver.sendmail(mailsender, mailreceip, msg.as_string()) mserver.quit() def check_aberration(rrdpath,fname): """ This will check for begin and end of aberration in file. Will return: 0 if aberration not found. 1 if aberration begins 2 if aberration ends """ ab_status = 0 rrdfilename = rrdpath+fname info = rrdtool.info(rrdfilename) rrdstep = int(info['step']) lastupdate = info['last_update'] previosupdate = str(lastupdate - rrdstep - 1) graphtmpfile = tempfile.NamedTemporaryFile() # Ready to get FAILURES from rrdfile # will process failures array values for time of 2 last updates values = rrdtool.graph(graphtmpfile.name, 'DEF:f0='+rrdfilename+':val:FAILURES:start='+previosupdate+':end='+str(lastupdate), 'PRINT:f0:MIN:%1.0lf', 'PRINT:f0:MAX:%1.0lf', 'PRINT:f0:LAST:%1.0lf') fmin = int(values[2][0]) fmax = int(values[2][1]) flast = int(values[2][2]) # check if failure value had changed. if (fmin != fmax): if (flast == 1): ab_status = 1 else: ab_status = 2 return ab_status def gen_image(rrdpath, pngpath, fname, width, height, begdate, enddate): """ Generates png file from rrd database: rrdpath - the path where rrd is located pngpath - the path png file should be created in fname - rrd file name, png file will have the same name .png extention width - chart area width height - chart area height begdate - unixtime enddate - unixtime """ # 24 hours before current time, will show on chart using SHIFT option ldaybeg = str(begdate - 86400) ldayend = str(enddate - 86400) # Will show some additional info on chart endd_str = time.strftime("%d/%m/%Y %H:%M:%S",(time.localtime(int(enddate)))).replace(':','\:') begd_str = time.strftime("%d/%m/%Y %H:%M:%S",(time.localtime(int(begdate)))).replace(':','\:') title = 'Chart for: '+fname.split('.')[0] # Files names pngfname = pngpath+fname.split('.')[0]+'.png' rrdfname = rrdpath+fname # Get iformation from rrd file info = rrdtool.info(rrdfname) rrdtype = info['ds[val].type'] # Will use multip variable for calculation of totals, # should be usefull for internet traffic accounting, # or call/minutes count from CDR's. # Do not need logic for DERIVE and ABSOLUTE if rrdtype == 'COUNTER': multip = str(int(enddate) - int(begdate)) else: # if value type is GAUGE should divide time to step value rrdstep = info['step'] multip = str(round((int(enddate) - int(begdate))/int(rrdstep))) # Make png image rrdtool.graph(pngfname, '--width',width,'--height',height, '--start',str(begdate),'--end',str(enddate),'--title='+title, '--lower-limit','0', '--slope-mode', 'COMMENT:From\:'+begd_str+' To\:'+endd_str+'\\c', 'DEF:value='+rrdfname+':val:AVERAGE', 'DEF:pred='+rrdfname+':val:HWPREDICT', 'DEF:dev='+rrdfname+':val:DEVPREDICT', 'DEF:fail='+rrdfname+':val:FAILURES', 'DEF:yvalue='+rrdfname+':val:AVERAGE:start='+ldaybeg+':end='+ldayend, 'SHIFT:yvalue:86400', 'CDEF:upper=pred,dev,2,*,+', 'CDEF:lower=pred,dev,2,*,-', 'CDEF:ndev=dev,-1,*', 'CDEF:tot=value,'+multip+',*', 'CDEF:ytot=yvalue,'+multip+',*', 'TICK:fail#FDD017:1.0:"Failures"\\n', 'AREA:yvalue#C0C0C0:"Yesterday\:"', 'GPRINT:ytot:AVERAGE:"Total\:%8.0lf"', 'GPRINT:yvalue:MAX:"Max\:%8.0lf"', 'GPRINT:yvalue:AVERAGE:"Average\:%8.0lf" \\n', 'LINE3:value#0000ff:"Value \:"', 'GPRINT:tot:AVERAGE:"Total\:%8.0lf"', 'GPRINT:value:MAX:"Max\:%8.0lf"', 'GPRINT:value:AVERAGE:"Average\:%8.0lf" \\n', 'LINE1:upper#ff0000:"Upper Bound "', 'LINE1:pred#ff00FF:"Forecast "', 'LINE1:ndev#000000:"Deviation "', 'LINE1:lower#00FF00:"Lower Bound "') # List of new aberrations begin_ab = [] # List of gone aberrations end_ab = [] # List files and generate charts for fname in os.listdir(rrdpath): gen_image(rrdpath, pngpath, fname, width, height, begdate, enddate) # Now check files for beiaberrations for fname in os.listdir(rrdpath): ab_status = check_aberration(rrdpath,fname) if ab_status == 1: begin_ab.append(fname) if ab_status == 2: end_ab.append(fname) if len(begin_ab) > 0: send_alert_attached('New aberrations detected',begin_ab) if len(end_ab) > 0: send_alert_attached('Abberations gone',end_ab) 

рдпрд╣ рдкрд┐рдЫрд▓реА рдкреЛрд╕реНрдЯ рдореЗрдВ рджреА рдЧрдИ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдПрдХ рд╕рдВрд╢реЛрдзрди рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдЕрдкрдХрд░реНрд╖рдг рдХреА рдЬрд╛рдБрдЪ рдХрд░рдиреЗ рдФрд░ рдореЗрд▓ рднреЗрдЬрдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдПрдБ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред

рдкреАрдПрд╕ рдореИрдВ рдЕрдЬрдЧрд░ рдореЗрдВ рд╕рдорд╛рдзрд╛рди рдХреА рдХреНрд╖рдорддрд╛ рдФрд░ рд╕реБрдВрджрд░рддрд╛ рдХреЛ рджреЗрдЦрдХрд░ рдЪрдХрд┐рдд рдирд╣реАрдВ рд╣реВрдВред

Source: https://habr.com/ru/post/In135086/


All Articles