рдЧреЛ рдкрд░ рдЯреАрд╕реАрдкреА / рдЖрдИрдкреА рдкреНрд░реЙрдХреНрд╕реА

рдореИрдВ рдирдИ рднрд╛рд╖рд╛рдУрдВ рдХреЛ рд╕реАрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдкрд╕рдВрджреАрджрд╛ рдХрд╛рдо рдкрд░ рд▓реМрдЯ рдЖрдпрд╛ред рдЧреЛ рдкрд░ рдмреНрд▓реЙрдЧ рдХреЗ рд▓рд┐рдП рдЗрдВрдЬрди рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВ рдЕрдкрдиреА рдЙрдВрдЧрд▓рд┐рдпреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЦреАрдВрдЪрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рдмреАрдорд╛рд░ рдЯреАрд╕реАрдкреА / рдЖрдИрдкреА рдкреНрд░реЙрдХреНрд╕реА / рдбреАрдмрдЧрд░ рдЕрдм рдЧреЛ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИред

рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдЯреАрд╕реАрдкреА / рдЖрдИрдкреА рдкреНрд░реЙрдХреНрд╕реА рдПрдХ рдРрд╕рд╛ рдХрд╛рд░реНрдпрдХреНрд░рдо рд╣реИ рдЬреЛ рдХрдиреЗрдХреНрд╢рди рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкрддреЗ рдкрд░ рдЕрдЧреНрд░реЗрд╖рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИред рд░рд╛рд╕реНрддреЗ рдХреЗ рд╕рд╛рде, рд╕рдВрдЪрд░рд┐рдд рдбреЗрдЯрд╛ рдХреЗ рд▓реЙрдЧ рдмрдирд╛рдП рд░рдЦреЗ рдЬрд╛рддреЗ рд╣реИрдВред рдпрд╣ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдЬрдм рд╡рд┐рднрд┐рдиреНрди рдШрд░-рдирд┐рд░реНрдорд┐рдд рдиреЗрдЯрд╡рд░реНрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЛ рдбреАрдмрдЧ рдХрд░рдирд╛ рд╣реИред

рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ, рдЧреЛ рд╕рдВрд╕реНрдХрд░рдг, рдПрд░реНрд▓рд╛рдВрдЧ рд╕рдВрд╕реНрдХрд░рдг рдХреА рддрд░рд╣, рддреАрди рд▓реЙрдЧ рд╣реИрдВ: рджреНрд╡рд┐-рджрд┐рд╢рд╛рддреНрдордХ рд╣реЗрдХреНрд╕рд╛рдбреЗрд╕рд┐рдорд▓ рдбрдВрдк рдФрд░ рдмрд╛рдЗрдирд░реА рд▓реЙрдЧ рджреЛрдиреЛрдВ рджрд┐рд╢рд╛рдУрдВ рдореЗрдВ, "рд╕реЗ" рдФрд░ "рд╕реЗ" рджреВрд░рд╕реНрде рд╣реЛрд╕реНрдЯ рддрдХред рдкрд╛рдпрдерди рд╕рдВрд╕реНрдХрд░рдг рдмрд╛рдЗрдирд░реА рд▓реЙрдЧ рдХрд╛ рдиреЗрддреГрддреНрд╡ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

рдмреЗрд╢рдХ, рд╕рдм рдХреБрдЫ рдмрд╣реБрдЖрдпрд╛рдореА рд╣реИред рдФрд░ рдЪреВрдВрдХрд┐ рдЧреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдЧреЛ рдореЗрдВ рдЗрддрдирд╛ рд╕рд░рд▓ (рдФрд░ рд╕реБрд░рдХреНрд╖рд┐рдд) рд╣реИ, рдЗрд╕рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдирд╛рдВрддрд░ рдЧрддрд┐рд╡рд┐рдзрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдПрд░рд▓рд╛рдВрдЧ рд╕рдВрд╕реНрдХрд░рдг рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╣реИред

Erlang рдкрд░, рдкреНрд░рддреНрдпреЗрдХ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЪрд╛рд░ рдкреНрд░рд╡рд╛рд╣ рдиреЗ рдХрд╛рдо рдХрд┐рдпрд╛:

рдЧреЛ рдкрд░ рд╕рдВрд╕реНрдХрд░рдг рдереЛрдбрд╝рд╛ рдЕрд▓рдЧ рд╣реИ:

рдХреБрд▓ 5ред

рджреЛрдиреЛрдВ рд╣реА рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ, рд▓реЙрдЧ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рд╕рдВрджреЗрд╢ рднреЗрдЬрдХрд░ рд╕реНрдЯреНрд░реАрдо рдбреЗрдЯрд╛ рд▓реЙрдЧ рдкрдврд╝реЗрдВред рдмреЗрд╢рдХ, рдореНрдпреВрдЯреЗрдХреНрд╕ рдпрд╛ рд╕рд╢рд░реНрдд рдЪрд░ рдЬреИрд╕реА рдХреЛрдИ рдмреЗрд╡рдХреВрдл рдЪреАрдЬреЗрдВ рдирд╣реАрдВ рд╣реИрдВред рдорд┐рд▓рд╛рди рдЪреИрдирд▓реЛрдВ рдХреЛ рдЧреЛ рдЪреИрдирд▓реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╢рд╛рдиреНрддрд┐рдкреВрд░реНрд╡рдХ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдиреАрдЪреЗ рд╕реНрд░реЛрдд рдХреЛрдб рд╣реИред рдпрд╣ рдкреНрд░рдЪреБрд░ рдорд╛рддреНрд░рд╛ рдореЗрдВ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рд╕реЗ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдЕрд▓рдЧ рд╣реИред рдЧреЛ рд╕реЗ рдмрд╣реБрдд рдкрд░рд┐рдЪрд┐рдд рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП, рдХреБрдЫ рдмрд┐рдВрджреБ рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред

package main import ( "flag" "fmt" "net" "os" "strings" "time" "encoding/hex" "runtime" ) var ( host *string = flag.String("host", "", "target host or address") port *string = flag.String("port", "0", "target port") listen_port *string = flag.String("listen_port", "0", "listen port") ) func die(format string, v ...interface{}) { os.Stderr.WriteString(fmt.Sprintf(format+"\n", v...)) os.Exit(1) } //       . func connection_logger(data chan []byte, conn_n int, local_info, remote_info string) { log_name := fmt.Sprintf("log-%s-%04d-%s-%s.log", format_time(time.Now()), conn_n, local_info, remote_info) logger_loop(data, log_name) } //     . func binary_logger(data chan []byte, conn_n int, peer string) { log_name := fmt.Sprintf("log-binary-%s-%04d-%s.log", format_time(time.Now()), conn_n, peer) logger_loop(data, log_name) } //     .  -   //  .   -      //  .     - . // func logger_loop(data chan []byte, log_name string) { f, err := os.Create(log_name) if err != nil { die("Unable to create file %s, %v\n", log_name, err) } defer f.Close() //      . for { b := <-data if len(b) == 0 { break } f.Write(b) f.Sync() //    flush'. } } func format_time(t time.Time) string { return t.Format("2006.01.02-15.04.05") } func printable_addr(a net.Addr) string { return strings.Replace(a.String(), ":", "-", -1) } // ,     . ,  //    . type Channel struct { from, to net.Conn logger, binary_logger chan []byte ack chan bool } // , ""         . //   . func pass_through(c *Channel) { from_peer := printable_addr(c.from.LocalAddr()) to_peer := printable_addr(c.to.LocalAddr()) b := make([]byte, 10240) offset := 0 packet_n := 0 for { n, err := c.from.Read(b) if err != nil { c.logger <- []byte(fmt.Sprintf("Disconnected from %s\n", from_peer)) break } if n > 0 { //  - ,      . c.logger <- []byte(fmt.Sprintf("Received (#%d, %08X) %d bytes from %s\n", packet_n, offset, n, from_peer)) //  ,      hex-. ,   ? c.logger <- []byte(hex.Dump(b[:n])) c.binary_logger <- b[:n] c.to.Write(b[:n]) c.logger <- []byte(fmt.Sprintf("Sent (#%d) to %s\n", packet_n, to_peer)) offset += n packet_n += 1 } } c.from.Close() c.to.Close() c.ack <- true //     ,   . } //    .      //  . func process_connection(local net.Conn, conn_n int, target string) { //    ,    . remote, err := net.Dial("tcp", target) if err != nil { fmt.Printf("Unable to connect to %s, %v\n", target, err) } local_info := printable_addr(remote.LocalAddr()) remote_info := printable_addr(remote.RemoteAddr()) //   . started := time.Now() //      . logger := make(chan []byte) from_logger := make(chan []byte) to_logger := make(chan []byte) //       . ack := make(chan bool) //  . go connection_logger(logger, conn_n, local_info, remote_info) go binary_logger(from_logger, conn_n, local_info) go binary_logger(to_logger, conn_n, remote_info) logger <- []byte(fmt.Sprintf("Connected to %s at %s\n", target, format_time(started))) //   . go pass_through(&Channel{remote, local, logger, to_logger, ack}) go pass_through(&Channel{local, remote, logger, from_logger, ack}) //     . <-ack <-ack //   . finished := time.Now() duration := finished.Sub(started) logger <- []byte(fmt.Sprintf("Finished at %s, duration %s\n", format_time(started), duration.String())) //    .       // ,         ,    //   . logger <- []byte{} from_logger <- []byte{} to_logger <- []byte{} } func main() { //  Go      . runtime.GOMAXPROCS(runtime.NumCPU()) //    (,   ?) flag.Parse() if flag.NFlag() != 3 { fmt.Printf("usage: gotcpspy -host target_host -port target_port -listen_post=local_port\n") flag.PrintDefaults() os.Exit(1) } target := net.JoinHostPort(*host, *port) fmt.Printf("Start listening on port %s and forwarding data to %s\n", *listen_port, target) ln, err := net.Listen("tcp", ":"+*listen_port) if err != nil { fmt.Printf("Unable to start listener, %v\n", err) os.Exit(1) } conn_n := 1 for { //   . if conn, err := ln.Accept(); err == nil { //    . go process_connection(conn, conn_n, target) conn_n += 1 } else { fmt.Printf("Accept failed, %v\n", err) } } } 

рдлрд┐рд░ рд╕реЗ, рдкреНрд░рддреНрдпреЗрдХ рдХрдиреЗрдХреНрд╢рди рдХреЛ рдкрд╛рдВрдЪ рдереНрд░реЗрдбреНрд╕ рджреНрд╡рд╛рд░рд╛ рдкрд░реЛрд╕рд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдореИрдВрдиреЗ рдЗрд╕реЗ рдордЬреЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдХрд┐рдпрд╛ред рдпрд╣ рд╕рд┐рд░реНрдл рдореБрдЭреЗ рд▓рдЧ рд░рд╣рд╛ рдерд╛ рдХрд┐ рддрд╛рд░реНрдХрд┐рдХ рд░реВрдк рд╕реЗ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕реНрд╡рддрдВрддреНрд░ рдЙрдк-рдореБрдЦреМрдЯреЗ рд╣реИрдВ рдЬреЛ рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддрд░реНрдХрд╕рдВрдЧрдд рд╣реЛрдВрдЧреЗред рдЕрдЧрд░ рдореИрдВрдиреЗ C ++ / рдмреВрд╕реНрдЯ рдореЗрдВ рд╕рдм рдХреБрдЫ рд▓рд┐рдЦрд╛ рд╣реИ, рддреЛ рдореИрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдзрд╛рдЧреЗ рдореЗрдВ рд╕рдм рдХреБрдЫ рдкрд┐рдШрд▓рд╛ рджреВрдВрдЧрд╛ (рдпрд╛ рд╢рд╛рдпрдж рдкреВрд░реЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдХреБрдЫ рдкрд░рд┐рд╖реНрдХреГрдд рдорд▓реНрдЯреАрдкреНрд▓реЗрдХреНрд╕рд┐рдВрдЧ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХрд▓-рдкрд┐рд░реЛрдпрд╛ рдЬрд╛рдПрдЧрд╛), рдФрд░ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдЕрдВрдд рдореЗрдВ C ++ ++ рдореЗрдВ рд╕рдВрднрд╡ рд╣реЛред рдпрд╣ рднреА рддреЗрдЬреА рд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рдПрдХ рдзрд╛рдЧреЗ рдХреЗ рдмрд╛рд╡рдЬреВрджред рд▓реЗрдХрд┐рди рдпрд╣ рд╡рд╣ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдореИрдВ рдХрд╣рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдорд▓реНрдЯреАрдереНрд░реЗрдбреЗрдб рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдкреБрд╢ (рдмрдЬрд╛рдп рдирдП рдорд╛рдирдХ рдХреЗ рд╕реНрдЯреЗрд░реЙрдпрдб рдкрд░ рднреА, рд╕реА ++ рдХреА рддрд░рд╣ рдкреБрд╢)ред рдПрдХ рдпрд╛ рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рд╕реЗ, рдРрд╕реЗ рдХрд╛рд░реНрдп рд╣реЛрдВрдЧреЗ рдЬрд╣рд╛рдВ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрд╛рд░рдХ рдмрди рдЬрд╛рдПрдЧрд╛ред

рдЖрдк рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ (рдХрдо рд╕реЗ рдХрдо рдЧреЛ рд░рд┐рд▓реАрдЬрд╝ 1 рдЖрд╡рд╢реНрдпрдХ рд╣реИ):

 go run gotcpspy.go -host pop.yandex.ru -port 110 -local_port 8080 

рдпрд╣ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ:

 Start listening on port 8080 and forwarding data to pop.yandex.ru:110 

рдлрд┐рд░, рдпрджрд┐ рдЖрдк рджреВрд╕рд░реА рд╡рд┐рдВрдбреЛ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддреЗ рд╣реИрдВ:

 telnet localhost 8080 

рдФрд░ рджрд░реНрдЬ рдХрд░реЗрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, " USER test " " ENTER " рдФрд░ " PASS none " " ENTER ", рддреЛ рддреАрди рд▓реЙрдЧ рдмрдирд╛рдП рдЬрд╛рдПрдВрдЧреЗ (рдирд╛рдо рдореЗрдВ рддрд╛рд░реАрдЦ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЕрд▓рдЧ рд╣реЛрдЧреА)ред

рд╕рд╛рдорд╛рдиреНрдп рд▓реЙрдЧ log-2012.04.20-19.55.17-0001-192.168.1.41-49544-213.180.204.37-110.log :

  Connected to pop.yandex.ru:110 at 2012.04.20-19.55.17 Received (#0, 00000000) 38 bytes from 192.168.1.41-49544 00000000 2b 4f 4b 20 50 4f 50 20 59 61 21 20 76 31 2e 30 |+OK POP Ya! v1.0| 00000010 2e 30 6e 61 40 32 36 20 48 74 6a 4a 69 74 63 50 |.0na@26 HtjJitcP| 00000020 52 75 51 31 0d 0a |RuQ1..| Sent (#0) to [--1]-8080 Received (#0, 00000000) 11 bytes from [--1]-8080 00000000 55 53 45 52 20 74 65 73 74 0d 0a |USER test..| Sent (#0) to 192.168.1.41-49544 Received (#1, 00000026) 23 bytes from 192.168.1.41-49544 00000000 2b 4f 4b 20 70 61 73 73 77 6f 72 64 2c 20 70 6c |+OK password, pl| 00000010 65 61 73 65 2e 0d 0a |ease...| Sent (#1) to [--1]-8080 Received (#1, 0000000B) 11 bytes from [--1]-8080 00000000 50 41 53 53 20 6e 6f 6e 65 0d 0a |PASS none..| Sent (#1) to 192.168.1.41-49544 Received (#2, 0000003D) 72 bytes from 192.168.1.41-49544 00000000 2d 45 52 52 20 5b 41 55 54 48 5d 20 6c 6f 67 69 |-ERR [AUTH] logi| 00000010 6e 20 66 61 69 6c 75 72 65 20 6f 72 20 50 4f 50 |n failure or POP| 00000020 33 20 64 69 73 61 62 6c 65 64 2c 20 74 72 79 20 |3 disabled, try | 00000030 6c 61 74 65 72 2e 20 73 63 3d 48 74 6a 4a 69 74 |later. sc=HtjJit| 00000040 63 50 52 75 51 31 0d 0a |cPRuQ1..| Sent (#2) to [--1]-8080 Disconnected from 192.168.1.41-49544 Disconnected from [--1]-8080 Finished at 2012.04.20-19.55.17, duration 5.253979s 

рдЖрдЙрдЯрдЧреЛрдЗрдВрдЧ рдмрд╛рдЗрдирд░реА рд▓реЙрдЧ log-binary-2012.04.20-19.55.17-0001-192.168.1.41-49544.log :

  USER test PASS none 

рдмрд╛рдЗрдирд░реА рдЗрдирдкреБрдЯ log-binary-2012.04.20-19.55.17-0001-213.180.204.37-110.log :

  +OK POP Ya! v1.0.0na@26 HtjJitcPRuQ1 +OK password, please. -ERR [AUTH] login failure or POP3 disabled, try later. sc=HtjJitcPRuQ1 

рдЕрдм рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдорд╛рдкреЗрдВред рд╣рдо рд╕реАрдзреЗ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдкрдВрдк рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЗрд╕ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗред

рд╕реАрдзреЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ (рдЖрдХрд╛рд░ рдореЗрдВ рд▓рдЧрднрдЧ 72MB рдлрд╝рд╛рдЗрд▓):

  time wget http://www.erlang.org/download/otp_src_R15B01.tar.gz ... Saving to: `otp_src_R15B01.tar.gz' ... real 1m2.819s 

рдЕрдм рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ, рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╕реЗ рдЪрд▓рд╛рдирд╛:

  go run gotcpspy.go -host=www.erlang.org -port=80 -listen_port=8080 

рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд░рд╣рд╛ рд╣реИ:

  time wget http://localhost:8080/download/otp_src_R15B01.tar.gz ... Saving to: `otp_src_R15B01.tar.gz.1' ... real 0m56.209s 

рдмрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдк рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

  diff otp_src_R15B01.tar.gz otp_src_R15B01.tar.gz.1

рдореЗрд░реА рдлрд╛рдЗрд▓реЗрдВ рд╕рдорд╛рди рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╕рдм рдХреБрдЫ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдЕрдм рд╕рдордп рд╣реИред рдореИрдВрдиреЗ рдХрдИ рдмрд╛рд░ рдкреНрд░рдпреЛрдЧ (рдореИрдХ рдПрдпрд░ рдкрд░) рджреЛрд╣рд░рд╛рдпрд╛, рдФрд░, рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд░реВрдк рд╕реЗ, рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдирд╛ рд╣рдореЗрд╢рд╛ рдЗрддрдирд╛ рдзреАрдорд╛ рдирд╣реАрдВ рдерд╛, рд▓реЗрдХрд┐рди рдереЛрдбрд╝рд╛ рддреЗрдЬ рднреАред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реАрдзреЗ - 1m2.819s, рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ - 0m56.209sред рдПрдХрдорд╛рддреНрд░ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдпрд╣ рд╣реИ рдХрд┐ wget рд╢рд╛рдпрдж рдПрдХ рдзрд╛рдЧреЗ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рджреЛ рдереНрд░реЗрдбреНрд╕ рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдФрд░ рджреВрд░рд╕реНрде рд╕реЙрдХреЗрдЯ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдереЛрдбрд╝рд╛ рддреНрд╡рд░рдг рджреЗ рд╕рдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди, рдЕрдВрддрд░ рдЕрднреА рднреА рдХрдо рд╕реЗ рдХрдо рд╣реИ, рдФрд░ рд╢рд╛рдпрдж рдпрд╣ рдХрд┐рд╕реА рдЕрдиреНрдп рдорд╢реАрди рдпрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрдЧрд╛, рд▓реЗрдХрд┐рди рдореБрдЦреНрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рд╣рд╕реНрддрд╛рдВрддрд░рдг рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рджреМрд░рд╛рди рдмрд╣реБрдд рдмрдбрд╝реЗ рд▓реЙрдЧ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдмрд╛рд╡рдЬреВрдж, рдХрдо рд╕реЗ рдХрдо рд╕реАрдзреЗ рдирд╣реАрдВ рдзреАрд░реЗ-рдзреАрд░реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдЗрд╕рд▓рд┐рдП, рдкрд╛рдпрдерди, рдПрд░реНрд▓реИрдВрдЧ рдФрд░ рдЧреЛ рдкрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рддреАрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдореЗрдВ рд╕реЗ, рдореБрдЭреЗ рд╕рдмрд╕реЗ рдЬреНрдпрд╛рджрд╛ рдкрд╕рдВрдж рд╣реИред

рдпрд╣ рдореБрдЭреЗ рдЧреЛ рдореЗрдВ рд╕рдорд╛рдирддрд╛ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдЪреНрдЫрд╛ рдкреНрд░рдпреЛрдЧ рд▓рдЧ рд░рд╣рд╛ рдерд╛ред

рд╕рдВрдмрдВрдзрд┐рдд рдкреЛрд╕реНрдЯ



рд░рд┐рдкреЛрдЬрд┐рдЯрд░реА рд▓рд┐рдВрдХ



рдкреБрдирд╢реНрдЪ


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

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


All Articles