존재하다bash
v4.1.2(2), 아래의 간단한 설명은 문제를 설명하기 위한 최소한의 예일 뿐이며 겉보기에 무작위 출력을 제공합니다.
$ for n in {0..1000}; do echo "$n"; done |
tee >(head -n2) >(sort -grk1,1 | head -n3) >/dev/null
다음은 일관된 출력을 제공합니다.
$ seq 0 10000 | tee >(head -n2) >(sort -grk1,1 | head -n3) >/dev/null
특히, 첫 번째 명령문의 경우 sort
명령은 무작위로 연속되는 트리플(예: 226,225,224; 52,51,50; 174,173,172 등)을 선택합니다. 출력의 이질성을 이해하려면 해당 명령을 여러 번 실행한 다음 다양한 가능성을 나열할 수 있습니다.
$ seq -w 0 2000 | while read x; do for n in {0..1000}; do echo "$n"; done |
tee >(head -n2) >(sort -grk1,1 | head -n3) >/dev/null | cat > "file_${x}"; done
다양한 출력의 발생 횟수를 계산합니다.
$ for f in file_*; do sort -g "$f" | tail -n3 | paste -sd, ; done |
sort | uniq -c | sort -gk1,1 -k2,2
1 7,8,9
1 17,18,19
1 40,41,42
1 43,44,45
1 47,48,49
1 50,51,52
1 54,55,56
1 58,59,60
1 59,60,61
1 66,67,68
1 71,72,73
1 78,79,80
1 103,104,105
1 104,105,106
1 106,107,108
1 110,111,112
1 111,112,113
1 121,122,123
1 125,126,127
1 129,130,131
1 134,135,136
1 136,137,138
1 142,143,144
1 143,144,145
1 148,149,150
1 150,151,152
1 156,157,158
1 157,158,159
1 165,166,167
1 171,172,173
1 173,174,175
1 174,175,176
1 177,178,179
1 179,180,181
1 181,182,183
1 183,184,185
1 185,186,187
1 186,187,188
1 191,192,193
1 194,195,196
1 198,199,200
1 200,201,202
1 206,207,208
1 208,209,210
1 209,210,211
1 210,211,212
1 216,217,218
1 217,218,219
1 233,234,235
1 236,237,238
1 237,238,239
1 238,239,240
1 242,243,244
1 245,246,247
1 246,247,248
1 254,255,256
1 256,257,258
1 267,268,269
1 270,271,272
1 273,274,275
1 277,278,279
1 279,280,281
1 287,288,289
1 288,289,290
1 305,306,307
1 306,307,308
1 307,308,309
1 326,327,328
1 337,338,339
1 339,340,341
1 340,341,342
1 351,352,353
1 357,358,359
1 359,360,361
1 365,366,367
1 368,369,370
1 370,371,372
1 376,377,378
1 377,378,379
1 383,384,385
1 386,387,388
1 388,389,390
1 401,402,403
1 408,409,410
1 409,410,411
1 415,416,417
1 419,420,421
1 424,425,426
1 426,427,428
1 432,433,434
1 454,455,456
1 462,463,464
1 466,467,468
1 475,476,477
1 482,483,484
1 487,488,489
1 504,505,506
1 508,509,510
1 511,512,513
1 532,533,534
1 538,539,540
1 544,545,546
1 548,549,550
1 558,559,560
1 603,604,605
1 604,605,606
1 608,609,610
1 659,660,661
1 660,661,662
1 663,664,665
1 668,669,670
1 692,693,694
1 699,700,701
1 717,718,719
1 738,739,740
1 740,741,742
1 750,751,752
1 771,772,773
1 784,785,786
1 796,797,798
1 799,800,801
1 806,807,808
1 814,815,816
1 832,833,834
1 848,849,850
1 858,859,860
1 869,870,871
1 922,923,924
1 952,953,954
1 961,962,963
1 985,986,987
2 64,65,66
2 127,128,129
2 141,142,143
2 169,170,171
2 170,171,172
2 172,173,174
2 187,188,189
2 221,222,223
2 234,235,236
2 252,253,254
2 292,293,294
2 350,351,352
2 364,365,366
2 375,376,377
2 622,623,624
2 666,667,668
3 70,71,72
3 102,103,104
3 137,138,139
3 155,156,157
1826 998,999,1000
결과의 정확도는 약 91%인 것으로 나타났습니다. >(head -n2)
명령문에서 프로세스 대체를 생략하면 tee
100% 올바른 출력이 생성됩니다. 경쟁 조건이 해석 질문과 관련된 이유를 이해하지 못합니다. 이는 명령문의 각 프로세스로 대체된 출력의 상대적 순서에만 영향을 미치기 때문입니다 tee
(즉, >(head -n2)
먼저 완료되거나 >(sort -grk1,1 | head -n3)
이 작업을 수행할 수 있지만 이는 결과 자체가 아니라 출력 순서입니다. 두 명령의 출력이 무작위로 인터리브되면 이해할 수 있습니다. 루프의 동일한 복사본이 tee
각 프로세스에 배포되어야 하고 두 프로세스 교체가 모두 별도의 하위 쉘에서 실행되기 때문입니다(stdout
stdin
>()
https://unix.stackexchange.com/a/331199/14960), 어느 쪽도 다른 쪽에게 영향을 주어서는 안 되지만 분명히 상호 작용합니다. 상호작용을 해석하는 방법은 무엇입니까? 또한 for
/ 루프 while
의 출력을 bash
여러 독립 프로세스에 어떻게 배포할 수 있습니까 tee
?
답변1
head -n2
두 줄을 읽은 후 종료됩니다. 그런 다음 tee
다음에 파이프에 기록될 때 (SIGPIPE로 인해) 죽고 head
, 지금까지 수신된 행을 기준으로 정렬된 자체 파이프의 다른 쪽 끝에서도 죽기 sort
때문에 eof를 보게 됩니다 .tee
seq가 아닌 루프에서 이를 보는 이유는 루프가 write()
파이프에서 여러 s를 실행하고 tee
시간에 따라 tee
여러 번의 짧은 읽기가 실행될 수 있기 때문입니다. seq
전체 출력이 한 번에 기록되지만 하나만 tee
수행됩니다 read()
. 이렇게 하면 seq 1000000
볼 수 있습니다.무작위의행동도 마찬가지다.
head
이 문제를 해결하려면 처음 두 줄을 출력한 후 계속해서 읽는 버전이 필요합니다 . 예를 들어 대신에 또는를 사용할 수 있습니다 sed '3,$d'
.head -n2
sed 2q
또는 다음을 사용하십시오:
... | (
trap '' PIPE
exec tee >(trap - PIPE; exec head -n2) >(trap - PIPE; sort -rn | head -n2)
) > /dev/null
SIGPIPE는 ( tee
만) 무시되지만 일부 tee
구현 에서는 write()
파이프가 실패하기 때문에 일부 오류 메시지가 표시됩니다.
tee: /proc/self/fd/13: I/O error
정렬된 출력은 다음과 같습니다.가능한정렬되지 않은 상태로 따르므로 보장되지 않습니다. 보다 일반적으로, 동시에 실행되는 프로그램을 조정하는 것이 없으면 출력 순서를 실제로 보장할 수 없습니다.