작동하지 않는 것

작동하지 않는 것

다음 스크립트를 실행 중입니다.

LOGDIR=~/curl_result_$(date |tr ' :' '_')

mkdir $LOGDIR

for THREADNO in $(seq 20)
do
for REQNO in $(seq 20)
do
 time curl --verbose -sS  http://dummy.restapiexample.com/api/v1/create --trace-ascii ${LOGDIR}/trace_${THREADNO}_${REQNO} -d @- <<EOF >> ${LOGDIR}/response_${THREADNO} 2>&1
 {"name":"emp_${THREADNO}_${REQNO}_$(date |tr ' :' '_')","salary":"$(echo $RANDOM%100000|bc)","age":"$(echo $RANDOM%100000|bc)"}
EOF
echo -e "\n-------------------------------" >> ${LOGDIR}/response_${THREADNO}
done 2>&1 | grep real > $LOGDIR/timing_${THREADNO} &
done

잠시 후 bash 프로세스가 없는지 확인하면 20(1 또는 21이 아님)이 표시됩니다.

ps|grep bash|wc -l

문제는 내부 루프를 둘러싸기 위해 대괄호 "()"를 사용하지 않기 때문에 새로운 쉘 프로세스가 생성되어서는 안 된다는 것입니다. CPU 사용량이 100%에 가까울 때 새 셸을 생성하지 않으려고 합니다. 이것이 중요한지는 모르겠지만 Cygwin을 사용하고 있습니다.

답변1

루프를 에 파이프했기 때문에 grep하위 쉘에서 실행되어야 합니다. 이 언급되었습니다배쉬 매뉴얼에서:

파이프라인의 각 명령은 별도의 프로세스인 자체 하위 셸에서 실행됩니다(참조:명령 실행 환경)

이는 다음을 통해 피할 수 있습니다.lastpipe주택 옵션~을 위한결정적인파이프라인에는 명령이 있지만 다른 명령에는 없습니다. 어쨌든 전체 파이프라인을 백그라운드에 두었습니다.반품서브셸을 만듭니다.

이 문제를 해결할 방법이 없습니다. 기본적으로 수행하는 작업에는 별도의 셸 프로세스가 필요합니다. 백그라운드 프로세스를 만들려면 파이프를 무시하더라도 프로세스를 만들어야 합니다.

문제가 CPU 사용량이라면 모든 것을 동시에 실행했기 때문에 발생한 것입니다. 제거하면 모든 명령 &grep동시에 실행되지 않고 순차적으로 실행됩니다. 하위 쉘은 여전히 ​​생성되지만(파이프용) 이 경우에는 그 자체로는 주요 문제가 아닙니다. 동시에 실행해야 하는 경우 CPU 사용량 증가를 선택하는 것이 좋습니다.

답변2

작동하지 않는 것

Bash는 스레드 병렬성을 지원하지 않고 다중 프로세스 병렬성을 지원합니다.

Bash는 하위 프로세스를 생성하지 않고는 백그라운드에서 for 루프(또는 파이프)를 실행할 수 없습니다. 놀랍게도 bash 프로세스는 21개가 아닌 20개입니다.

저는 Cygwin에 대해 아무것도 모릅니다.


대안

Python에 익숙하다면 Plumbum 라이브러리를 사용하는 것이 좋습니다. Python은 스레드를 지원하므로 모든 것이 더 쉬워집니다.

다시 작성하고 테스트한 코드는 다음과 같습니다.

from datetime import datetime
import json
import random
from plumbum import cmd as c
from threading import Thread

def now():
    return datetime.now().strftime("%Y-%m-%d %H_%M_%S")

logdir = f"~/curl_result_{now()}"

def curl(threadno, reqno):
    args1 = "--verbose -sS http://dummy.restapiexample.com/api/v1/create --trace-ascii".split()
    args2 = [f"{logdir}_{threadno}_{reqno}", "-d", "@-"]
    content = json.dumps({
        "name": f"{logdir}/trace_{threadno}_{reqno}_{now()}",
        "salary": random.randrange(100_000),
        "age": random.randrange(100_000) ,
    })
    call = c.echo[content] | c.curl[(*args1, *args2)] >> f"{logdir}/response_{threadno}"
    print(call)
    # call()

def curl_batch(threadno):
    for reqno in range(20):
        curl(threadno, reqno)

# Start 20 threads
threadList = []
for threadno in range(20):
    t = Thread(target=curl_batch, args=(threadno,))
    t.start()
    threadList.append(t)

# Wait for every thread
for thread in threadList:
    thread.join()

Python의 유연성을 즐겨보세요 ;)

관련 정보