рд▓рд┐рдирдХреНрд╕ рдкрд╛рдЗрдк рдпреБрдХреНрддрд┐рдпрд╛рдБ рдФрд░ рдЪрд╛рд▓реЗрдВ

рдкрд╛рдЗрдк - рдпрд╣ рдХреНрдпрд╛ рд╣реИ?


рдкрд╛рдЗрдк (рдХрдиреНрд╡реЗрдпрд░) рдЗрдВрдЯрд░рдкреНрд░реЛрд╕реЗрд╕ рд╕рдВрдЪрд╛рд░ рдХрд╛ рдПрдХ рдпреВрдирд┐рдбрд╛рдпрд░реЗрдХреНрд╢рдирд▓ рдЪреИрдирд▓ рд╣реИред рдЗрд╕ рд╢рдмреНрдж рдХреЛ рдбрдЧрд▓рд╕ рдореИрдХрд▓рд╛рд░реЙрдп рдиреЗ рдпреВрдирд┐рдХреНрд╕ рд╢реЗрд▓ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдерд╛ рдФрд░ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЗ рдирд╛рдо рдкрд░ рд░рдЦрд╛ рдЧрдпрд╛ рдерд╛ред рдкрд╛рдЗрдкрд▓рд╛рдЗрдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдХреНрд╕рд░ рд╢реЗрд▓ рд▓рд┐рдкрд┐рдпреЛрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдПрдХ рдХрдорд╛рдВрдб (рд╕реНрдЯрдбрдЖрдЙрдЯ) рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдХрдИ рдХрдорд╛рдВрдбрд░реНрд╕ рд╕реЗ рд▓рд┐рдВрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ, рдЬреЛ рдХрд┐ рдХрдВрд╡реЗрдВрдЯрд░ рд╕рд┐рдВрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдмрд╛рдж рдХреЗ рдЗрдирдкреБрдЯ (рд╕реНрдЯрдб) рдХреЛ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рддрд╛ рд╣реИред '': '
cmd1 | cmd2 | .... | cmdN 

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:
 $ grep -i тАЬerrorтАЭ ./log | wc -l 43 

grep рд▓реЙрдЧ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕реНрдЯреНрд░рд┐рдВрдЧ "рддреНрд░реБрдЯрд┐" рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЗрд╕-рдЕрд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдЦреЛрдЬ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЦреЛрдЬ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рджрд░реНрд╢рд┐рдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди wc рдХрдорд╛рдВрдб рдХреЗ рдЗрдирдкреБрдЯ (рд╕реНрдЯрдбрд┐рди) рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рд▓рд╛рдЗрдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИред

рддрд░реНрдХ


рдкрд╛рдЗрдкрд▓рд╛рдЗрди I / O рдмрдлрд░рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрджреЗрд╢реЛрдВ рдХреЗ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рд╕рднреА рдХрдорд╛рдВрдб рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдкреНрд░рддреНрдпреЗрдХ рдЕрдкрдиреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВред

рдХрд░реНрдиреЗрд▓ рд╕рдВрд╕реНрдХрд░рдг 2.6.11 рдХреЗ рдмрд╛рдж рд╕реЗ рдмрдлрд░ рдХрд╛ рдЖрдХрд╛рд░ 65536 рдмрд╛рдЗрдЯреНрд╕ (64 рдХреЗрдмреА) рд╣реИ рдФрд░ рдкреБрд░рд╛рдиреЗ рдХрд░реНрдиреЗрд▓ рдореЗрдВ рдореЗрдореЛрд░реА рдкреЗрдЬ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред рдЬрдм рдЖрдк рдЦрд╛рд▓реА рдмрдлрд╝рд░ рд╕реЗ рдкрдврд╝рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдбреЗрдЯрд╛ рджрд┐рдЦрд╛рдИ рджреЗрдиреЗ рддрдХ рдкрдврд╝рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЕрд╡рд░реБрджреНрдз рд╣реЛ рдЬрд╛рддреА рд╣реИред рдЗрд╕реА рддрд░рд╣, рдпрджрд┐ рдЖрдк рдПрдХ рднрд░реЗ рд╣реБрдП рдмрдлрд░ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм рддрдХ рдХрд┐ рдЖрд╡рд╢реНрдпрдХ рд╕реНрдерд╛рди рдХреЛ рдореБрдХреНрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдЗрдирдкреБрдЯ / рдЖрдЙрдЯрдкреБрдЯ рдзрд╛рд░рд╛рдУрдВ рдХреЗ рдлрд╝рд╛рдЗрд▓ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдкрд░ рдЪрд▓ рд░рд╣реА рд╣реИ, рдбрд┐рд╕реНрдХ рдХреЛ рд▓реЛрдб рдХрд┐рдП рдмрд┐рдирд╛ рд╕рднреА рдСрдкрд░реЗрд╢рди рдореЗрдореЛрд░реА рдореЗрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
рдиреАрдЪреЗ рджреА рдЧрдИ рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА bash-4.2 рд╢реЗрд▓ рдФрд░ 3.10.10 рдХрд░реНрдиреЗрд▓ рдХреЗ рд▓рд┐рдП рд╣реИред

рд╕рд╛рдзрд╛рд░рдг рдбрд┐рдмрдЧ


рд╕реНрдЯреНрд░реАрдо рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдЖрдкрдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ:
 $ strace -f bash -c '/bin/echo foo | grep bar' .... getpid() = 13726 <тАУ PID   ... pipe([3, 4]) <тАУ      .... clone(....) = 13727 <тАУ      (echo) ... [pid 13727] execve("/bin/echo", ["/bin/echo", "foo"], [/* 61 vars */] ..... [pid 13726] clone(....) = 13728 <тАУ     (grep)      ... [pid 13728] stat("/home/aikikode/bin/grep", ... 
рдпрд╣ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдХрдиреНрд╡реЗрдпрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рдЗрдк () рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рднреА рдХрд┐ рджреЛрдиреЛрдВ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдзрд╛рдЧреЗ рдореЗрдВ рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдмрд╣реБрдд рд╕рд╛рд░реЗ рдмреИрд╢ рд╕реЛрд░реНрд╕ рдХреЛрдб рдФрд░ рдХрд░реНрдиреЗрд▓

рд╕реНрд░реЛрдд рдХреЛрдб, рд╕реНрддрд░ 1, рд╢реЗрд▓


рдЪреВрдВрдХрд┐ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдкреНрд░рд▓реЗрдЦрди рд╕реНрд░реЛрдд рдХреЛрдб рд╣реИ, рд╣рдо рдЗрд╕реЗ рдЪрд╛рд▓реВ рдХрд░реЗрдВрдЧреЗред рдмреИрд╢ рдЗрдирдкреБрдЯ рдХрдорд╛рдВрдбреНрд╕ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Yacc рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ 'рдХрдорд╛рдВрдб_рдХрдиреЗрдХреНрдЯ ()' рд░рд┐рдЯрд░реНрди рджреЗрддрд╛ рд╣реИ рдЬрдм рдпрд╣ рдХреИрд░реЗрдХреНрдЯрд░ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддрд╛ рд╣реИред
parse.y :
 1242 pipeline: pipeline '|' newline_list pipeline 1243 { $$ = command_connect ($1, $4, '|'); } 1244 | pipeline BAR_AND newline_list pipeline 1245 { 1246 /* Make cmd1 |& cmd2 equivalent to cmd1 2>&1 | cmd2 */ 1247 COMMAND *tc; 1248 REDIRECTEE rd, sd; 1249 REDIRECT *r; 1250 1251 tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1; 1252 sd.dest = 2; 1253 rd.dest = 1; 1254 r = make_redirection (sd, r_duplicating_output, rd, 0); 1255 if (tc->redirects) 1256 { 1257 register REDIRECT *t; 1258 for (t = tc->redirects; t->next; t = t->next) 1259 ; 1260 t->next = r; 1261 } 1262 else 1263 tc->redirects = r; 1264 1265 $$ = command_connect ($1, $4, '|'); 1266 } 1267 | command 1268 { $$ = $1; } 1269 ; 
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдпрд╣рд╛рдВ '' | & '' рдХреА рдПрдХ рдЬреЛрдбрд╝реА рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рдЬреЛ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ stdout рдФрд░ stderr рджреЛрдиреЛрдВ рдХреЛ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж, command_connect (): make_cmd.c рдХреА рдУрд░ рдореБрдбрд╝реЗрдВ :
 194 COMMAND * 195 command_connect (com1, com2, connector) 196 COMMAND *com1, *com2; 197 int connector; 198 { 199 CONNECTION *temp; 200 201 temp = (CONNECTION *)xmalloc (sizeof (CONNECTION)); 202 temp->connector = connector; 203 temp->first = com1; 204 temp->second = com2; 205 return (make_command (cm_connection, (SIMPLE_COM *)temp)); 206 } 
рдЬрд╣рд╛рдВ рдХрдиреЗрдХреНрдЯрд░ рдЪрд░рд┐рддреНрд░ рд╣реИ '|' рдЗрдВрдЯ рдХреА рддрд░рд╣ред рдЖрджреЗрд╢реЛрдВ рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╕рдордп ('&', '|', ';', рдЗрддреНрдпрд╛рджрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ), execute_connection () рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ: execute_cmd.c :
 2325 case '|': ... 2331 exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close); 

PIPE_IN рдФрд░ PIPE_OUT рдлрд╝рд╛рдЗрд▓ рд╡рд┐рд╡рд░рдг рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рдЗрдирдкреБрдЯ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╣реИред рд╡реЗ рдорд╛рди NO_PIPE рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ I / O рд╕реНрдЯрдб / рд╕реНрдЯрдбрдЖрдЙрдЯ рд╣реИред
execute_pipeline () рдПрдХ рдмрдбрд╝рд╛ рдХрд╛рдо рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдХреНрд░рд┐рдпрд╛рдиреНрд╡рдпрди execute_cmd.c рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИред рд╣рдо рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рд╣рд┐рд╕реНрд╕реЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред
execute_cmd.c :
 2112 prev = pipe_in; 2113 cmd = command; 2114 2115 while (cmd && cmd->type == cm_connection && 2116 cmd->value.Connection && cmd->value.Connection->connector == '|') 2117 { 2118 /*      */ 2119 if (pipe (fildes) < 0) 2120 { /*   */ } ....... /*     ,      prev тАФ   ,     fildes[1] тАФ   ,     pipe() */ 2178 execute_command_internal (cmd->value.Connection->first, asynchronous, 2179 prev, fildes[1], fd_bitmap); 2180 2181 if (prev >= 0) 2182 close (prev); 2183 2184 prev = fildes[0]; /*        */ 2185 close (fildes[1]); ....... 2190 cmd = cmd->value.Connection->second; /* тАЬтАЭ      */ 2191 } 
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдмреИрд╢ рдкрд╛рдЗрдк () рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдХреЛ рдкреНрд░рддреНрдпреЗрдХ '' | '' рд╡рд░реНрдг рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдХреЗ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдкреНрд░рддреАрдХ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИред рдФрд░ рдЗрдирдкреБрдЯ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреБрдХреНрдд рдлрд╝рд╛рдЗрд▓ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЕрд▓рдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХрдорд╛рдВрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ рд╣реИред

рд╕реНрд░реЛрдд рдХреЛрдб, рд╕реНрддрд░ 2, рдХрд░реНрдиреЗрд▓


рд╣рдо рдХрд░реНрдиреЗрд▓ рдХреЛрдб рдХреА рдУрд░ рдореБрдбрд╝рддреЗ рд╣реИрдВ рдФрд░ рдкрд╛рдЗрдк () рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВред рдпрд╣ рдЖрд▓реЗрдЦ рдХрд░реНрдиреЗрд▓ рд╕рдВрд╕реНрдХрд░рдг 3.10.10 рд╕реНрдерд┐рд░ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рддрд╛ рд╣реИред
fs / pip.c (рдЗрд╕ рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдкрд▓рдмреНрдз рдХреЛрдб рд╕реНрдирд┐рдкреЗрдЯ):
 /*       .       /proc/sys/fs/pipe-max-size */ 35 unsigned int pipe_max_size = 1048576; /*    ,   POSIX     , .. 4 */ 40 unsigned int pipe_min_size = PAGE_SIZE; 869 int create_pipe_files(struct file **res, int flags) 870 { 871 int err; 872 struct inode *inode = get_pipe_inode(); 873 struct file *f; 874 struct path path; 875 static struct qstr name = {. name = тАЬтАЭ }; /*  dentry  dcache */ 881 path.dentry = d_alloc_pseudo(pipe_mnt->mnt_sb, &name); /*     file.    FMODE_WRITE,     O_WRONLY, ..             .   O_NONBLOCK   . */ 889 f = alloc_file(&path, FMODE_WRITE, &pipefifo_fops); 893 f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)); /*      file   (. FMODE_READ   O_RDONLY) */ 896 res[0] = alloc_file(&path, FMODE_READ, &pipefifo_fops); 902 res[0]->f_flags = O_RDONLY | (flags & O_NONBLOCK); 903 res[1] = f; 904 return 0; 917 } 918 919 static int __do_pipe_flags(int *fd, struct file **files, int flags) 920 { 921 int error; 922 int fdw, fdr; /*   file     (.  ) */ 927 error = create_pipe_files(files, flags); /*     */ 931 fdr = get_unused_fd_flags(flags); 936 fdw = get_unused_fd_flags(flags); 941 audit_fd_pair(fdr, fdw); 942 fd[0] = fdr; 943 fd[1] = fdw; 944 return 0; 952 } /*    int pipe2(int pipefd[2], int flags)... */ 969 SYSCALL_DEFINE2(pipe2, int __user *, fildes, int, flags) 970 { 971 struct file *files[2]; 972 int fd[2]; /*    /     */ 975 __do_pipe_flags(fd, files, flags); /*     kernel space  user space */ 977 copy_to_user(fildes, fd, sizeof(fd)); /*       */ 984 fd_install(fd[0], files[0]); 985 fd_install(fd[1], files[1]); 989 } /* ... int pipe(int pipefd[2]),        pipe2   ; */ 991 SYSCALL_DEFINE1(pipe, int __user *, fildes) 992 { 993 return sys_pipe2(fildes, 0); 994 } 
рдпрджрд┐ рдЖрдкрдиреЗ рджреЗрдЦрд╛, рддреЛ рдХреЛрдб O_NONBLOCK рдзреНрд╡рдЬ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХрд░ рд░рд╣рд╛ рд╣реИред рдЗрд╕реЗ fcntl рдореЗрдВ F_SETFL рдСрдкрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╡рд╣ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ I / O рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд┐рдП рдмрд┐рдирд╛ рдореЛрдб рдореЗрдВ рд╕реНрд╡рд┐рдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рдЗрд╕ рдореЛрдб рдореЗрдВ, рд▓реЙрдХ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рд╕реНрдЯреНрд░реАрдо рдХреЛ рдкрдврд╝рдиреЗ / рд▓рд┐рдЦрдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЧрд▓рдд рдХреЛрдб EAGAIN рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рдПрдЧреАред

рдкрд╛рдЗрдк рдХреЛ рд▓рд┐рдЦреЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдЯрд╛ рдмреНрд▓реЙрдХ рдХрд╛ рдЕрдзрд┐рдХрддрдо рдЖрдХрд╛рд░ рд╣рд╛рде рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА (4K) рдХрд╛ рдПрдХ рдкреГрд╖реНрда рд╣реИ:
рдореЗрд╣рд░рд╛рдм / рдмрд╛рдВрд╣ / рд╢рд╛рдорд┐рд▓ / asm / limit.h :
  8 #define PIPE_BUF PAGE_SIZE 
рдЧреБрдард▓реА рдХреЗ рд▓рд┐рдП> = 2.6.35, рдЖрдк рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдмрдлрд░ рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ:
 fcntl(fd, F_SETPIPE_SZ, <size>) 
рдЕрдзрд┐рдХрддрдо рдЕрдиреБрдордд рдмрдлрд░ рдЖрдХрд╛рд░, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдКрдкрд░ рджреЗрдЦрд╛, рдлрд╝рд╛рдЗрд▓ / proc / sys / fs / рдкрд╛рдЗрдк-рдЕрдзрд┐рдХрддрдо-рдЖрдХрд╛рд░ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИред

рдЯрд┐рдкреНрд╕ рдФрд░ рдЯреНрд░рд┐рдХреНрд╕


рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ, рд╣рдо рдореМрдЬреВрджрд╛ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдФрд░ рджреЛ рдЧреИрд░-рдореМрдЬреВрдж рдлрд╝рд╛рдЗрд▓реЛрдВ рдкрд░ ls рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВрдЧреЗ: ./non-existent_file рдФрд░ред / other_non- рдореМрдЬреВрдж_рдлрд╛рдЗрд▓ред

  1. рджреЛрдиреЛрдВ stdout рдФрд░ stderr рдХреЛ рдкрд╛рдЗрдк рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рдирд╛

     ls -d ./Documents ./non-existent_file ./other_non-existent_file 2>&1 | egrep тАЬDoc|otherтАЭ ls: cannot access ./other_non-existent_file: No such file or directory ./Documents 
    рдпрд╛ рдЖрдк рдЕрдХреНрд╖рд░реЛрдВ рдХреЗ рд╕рдВрдпреЛрдЬрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ '| &' (рдЖрдк рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдбреЙрдХреНрдпреВрдореЗрдВрдЯ рд╕реЗ рд╢реЗрд▓ (рдореИрди рдмреИрд╢) рдФрд░ рдКрдкрд░ рдХреЗ рд╕реНрд░реЛрддреЛрдВ рд╕реЗ, рдЬрд╣рд╛рдБ рд╣рдордиреЗ рдпрд╛рдХ рдкрд╛рд░реНрд╕рд░ рдмреИрд╢ рдкрд░ рджреЗрдЦрд╛ рдерд╛) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ:
     ls -d ./Documents ./non-existent_file ./other_non-existent_file |& egrep тАЬDoc|otherтАЭ ls: cannot access ./other_non-existent_file: No such file or directory ./Documents 

  2. рдЕрдиреБрдкреНрд░реЗрд╖рд┐рдд _only_ stderr рд╕реЗ рдкрд╛рдЗрдк

     $ ls -d ./Documents ./non-existent_file ./other_non-existent_file 2>&1 >/dev/null | egrep тАЬDoc|otherтАЭ ls: cannot access ./other_non-existent_file: No such file or directory 
    рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдкреИрд░ рдореЗрдВ рдЧреЛрд▓реА рдорд╛рд░реЛ
    рд╕реНрдЯрдбрдЖрдЙрдЯ рдФрд░ рд╕реНрдЯреЗрдбрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рди рдЖрджреЗрд╢ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рдВрдпреЛрдЬрди>> / рджреЗрд╡ / рдЕрд╢рдХреНрдд 2> рдФрд░ 1 out рджреЛрдиреЛрдВ stdout рдФрд░ stderr рдХреЛ / dev / null рдореЗрдВ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░реЗрдЧрд╛ред

  3. рд╕рд╣реА рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд╕рдорд╛рдкреНрддрд┐ рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛

    рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд╕рдорд╛рдкреНрддрд┐ рдХреЛрдб рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рдЕрдВрддрд┐рдо рдХрдорд╛рдВрдб рдХрд╛ рд╕рдорд╛рдкреНрддрд┐ рдХреЛрдб рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореВрд▓ рдХрдорд╛рдВрдб рд▓реЗрдВ, рдЬреЛ рдПрдХ рдЧреИрд░-рд╢реВрдиреНрдп рдХреЛрдб рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддреА рд╣реИ:
     $ ls -d ./non-existent_file 2>/dev/null; echo $? 2 
    рдФрд░ рдЗрд╕реЗ рдкрд╛рдЗрдк рдореЗрдВ рдбрд╛рд▓реЗрдВ:
     $ ls -d ./non-existent_file 2>/dev/null | wc; echo $? 0 0 0 0 
    рдЕрдм рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд╕рдорд╛рдкреНрддрд┐ рдХреЛрдб wc рдХрдорд╛рдВрдб рд╕рдорд╛рдкреНрддрд┐ рдХреЛрдб рд╣реИ, рдЕрд░реНрдерд╛рдд 0ред

    рдЖрдорддреМрд░ рдкрд░, рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдХреНрдпрд╛ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реБрдИ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, pipefail рд╡рд┐рдХрд▓реНрдк рд╕реЗрдЯ рдХрд░реЗрдВ, рдЬреЛ рд╢реЗрд▓ рдХреЛ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рд╕рдорд╛рдкреНрддрд┐ рдХреЛрдб рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХрдорд╛рдВрдб рдпрд╛ рд╢реВрдиреНрдп рдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдПрдХ рдХреЗ рдкрд╣рд▓реЗ рдЧреИрд░-рд╢реВрдиреНрдп рд╕рдорд╛рдкреНрддрд┐ рдХреЛрдб рдХреЗ рд╕рд╛рде рдореЗрд▓ рдЦрд╛рдПрдЧрд╛ рдпрджрд┐ рд╕рднреА рдХрдорд╛рдВрдб рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдкреВрд░рд╛ рд╣реЛ:
     $ set -o pipefail $ ls -d ./non-existent_file 2>/dev/null | wc; echo $? 0 0 0 2 
    рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдкреИрд░ рдореЗрдВ рдЧреЛрд▓реА рдорд╛рд░реЛ
    "рд╣рд╛рдирд┐рд░рд╣рд┐рдд" рдЖрджреЗрд╢реЛрдВ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦреЗрдВ рдЬреЛ рдЧреИрд░-рд╢реВрдиреНрдп рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рди рдХреЗрд╡рд▓ рдХрдиреНрд╡реЗрдпрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, grep рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
     $ egrep тАЬ^foo=[0-9]+тАЭ ./config | awk '{print тАЬnew_тАЭ$0;}' 
    рдпрд╣рд╛рдВ рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдкрдВрдХреНрддрд┐ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ 'new_' рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рд╕рднреА рд▓рд╛рдЗрдиреЛрдВ рдХреЛ рдкреНрд░рд┐рдВрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╛ рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рд╛рд░реВрдк рдХреА рдХреЛрдИ рднреА рд░реЗрдЦрд╛ рдирд╣реАрдВ рдорд┐рд▓рдиреЗ рдкрд░ рдХреБрдЫ рднреА рдкреНрд░рд┐рдВрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЕрдЧрд░ рдХреЛрдИ рдореЗрд▓ рдирд╣реАрдВ рдорд┐рд▓рд╛, рддреЛ grep рдХреЛрдб 1 рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рд╣рдорд╛рд░реА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ pipefail рд╡рд┐рдХрд▓реНрдк рд╕реЗрдЯ рд╣реИ, рддреЛ рдпрд╣ рдЙрджрд╛рд╣рд░рдг рдХреЛрдб 1 рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рдПрдЧрд╛:
     $ set -o pipefail $ egrep тАЬ^foo=[0-9]+тАЭ ./config | awk '{print тАЬnew_тАЭ$0;}' >/dev/null; echo $? 1 
    рдЬрдЯрд┐рд▓ рдбрд┐рдЬрд╛рдЗрди рдФрд░ рд▓рдВрдмреЗ рдХрдиреНрд╡реЗрдпрд░ рдХреЗ рд╕рд╛рде рдмрдбрд╝реА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ, рдЗрд╕ рдмрд┐рдВрджреБ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЧрд▓рдд рдкрд░рд┐рдгрд╛рдо рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред

  4. рдПрдХ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рдЪрд░ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рд╕реМрдВрдкрдирд╛

    рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдпрд╛рдж рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рд╕рднреА рдХрдорд╛рдВрдбреЛрдВ рдХреЛ рдХреНрд▓реЛрди () рдХрд╣рдХрд░ рдкреНрд░рд╛рдкреНрдд рдХреА рдЧрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдпрд╣ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рдХрд╛рд░рдг рдирд╣реАрдВ рдмрдирддрд╛ рд╣реИ, рдЪрд░ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рдеред
    рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
     $ a=aaa $ b=bbb $ echo тАЬone twoтАЭ | read ab 
    рд╣рдо рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдЕрдм рдЪрд░ рдФрд░ рдмреА рдХреЗ рдорд╛рди рдХреНрд░рдорд╢рдГ "рдПрдХ" рдФрд░ "рджреЛ" рд╣реЛрдВрдЧреЗред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╡реЗ "рдЖ" рдФрд░ "рдмрдмреНрдм" рд░рд╣реЗрдВрдЧреЗред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдЗрд╕рдХреЗ рдмрд╛рд╣рд░ рдкрд╛рдЗрдк рд▓рд╛рдЗрди рдореЗрдВ рдЪрд░ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рдХреЛрдИ рднреА рдкрд░рд┐рд╡рд░реНрддрди рдЪрд░ рдХреЛ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд рдЫреЛрдбрд╝ рджреЗрдЧрд╛:
     $ filefound=0 $ find . -type f -size +100k | while true do read f echo тАЬ$f is over 100KBтАЭ filefound=1 break #      done $ echo $filefound; 
    рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЕрдЧрд░ рдХреЛрдИ рдлрд╝рд╛рдЗрд▓ 100Kb рд╕реЗ рдмрдбрд╝реА рд▓рдЧрддреА рд╣реИ, рддрдм рднреА рдлрд╝рд╛рдЗрд▓рдлрд╝рд╛рдЙрдВрдб рдзреНрд╡рдЬ рдХрд╛ рдорд╛рди 0 рд╣реЛрдЧрд╛ред
    рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЗ рдХрдИ рд╕рдорд╛рдзрд╛рди рд╕рдВрднрд╡ рд╣реИрдВ:
    • рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
       set -- $var 

      рдпрд╣ рдирд┐рд░реНрдорд╛рдг рдЪрд░ рдЪрд░ рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕реНрдерд┐рддреАрдп рдЪрд░ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рджрд┐рдП рдЧрдП рдкрд╣рд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╣реИ:
       $ var=тАЭone twoтАЭ $ set -- $var $ a=$1 # тАЬoneтАЭ $ b=$2 # тАЬtwoтАЭ 
      рдпрд╣ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ, рдореВрд▓ рд╕реНрдерд┐рддреАрдп рдкреИрд░рд╛рдореАрдЯрд░ рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдЗрд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЦреЛ рдЬрд╛рдПрдЧрд╛ред
    • рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рдПрдХ рд╣реА рдЙрдкрдкреНрд░рдХрд╛рд░ рдХреЗ рдЪрд░ рдореВрд▓реНрдп рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд╕рднреА рддрд░реНрдХ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВ:
       $ echo тАЬoneтАЭ | (read a; echo $a;) one 
    • рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЗ рдЕрдВрджрд░ рдЪрд░реЛрдВ рдХреЛ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рддрд░реНрдХ рдмрджрд▓реЗрдВред
      рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд╕рд╛рде рдмрджрд▓реЗрдВ:
       $ filefound=0 $ for f in $(find . -type f -size +100k) #   ,     do read f echo тАЬ$f is over 100KBтАЭ filefound=1 break done $ echo $filefound; 
    • (рдХреЗрд╡рд▓ рдмреИрд╢-4.2 рдФрд░ рдирдП рдХреЗ рд▓рд┐рдП) рд▓рд╛рд╕реНрдЯрдкрд╛рдЗрдк рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
      рд▓рд╛рд╕реНрдЯрдкрд╛рдЗрдк рд╡рд┐рдХрд▓реНрдк рд╢реЗрд▓ рдХреЛ рдореБрдЦреНрдп рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдЕрдВрддрд┐рдо рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХрдорд╛рдВрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрджреЗрд╢ рджреЗрддрд╛ рд╣реИред
       $ (shopt -s lastpipe; a=тАЭaaaтАЭ; echo тАЬoneтАЭ | read a; echo $a) one 
      рдпрд╣ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рд▓рд╛рд╕реНрдЯрдкрд╛рдЗрдк рд╡рд┐рдХрд▓реНрдк рдХреЛ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдкрд░ рдЙрд╕реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд╣рд╛рдВ рдЗрд╕реА рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдКрдкрд░ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдХреЛрд╖реНрдардХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд▓рд┐рдкрд┐рдпреЛрдВ рдореЗрдВ, рдХреЛрд╖реНрдардХ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╣реИрдВред

рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдирдХрд╛рд░реА


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


All Articles