首页 文章

如何在bash中等待几个子进程完成并返回退出代码!= 0当任何子进程以代码结束时!= 0?

提问于
浏览
441

如何在bash脚本中等待从该脚本生成的几个子进程完成并返回退出代码!= 0当任何子进程以代码结束时!= 0?

简单的脚本:

#!/bin/bash
for i in `seq 0 9`; do
  doCalculations $i &
done
wait

上面的脚本将等待所有10个生成的子进程,但它总是会给出退出状态0(参见 help wait ) . 如何修改此脚本,以便发现生成的子进程的退出状态,并在任何子进程以代码!= 0结束时返回退出代码1?

有没有更好的解决方案,而不是收集子流程的PID,按顺序等待它们并汇总退出状态?

27 回答

  • 38

    wait也(可选)使进程的PID等待,并使用$!你得到在后台启动的最后一个命令的PID . 修改循环以将每个生成的子进程的PID存储到数组中,然后再次循环等待每个PID .

    # run processes and store pids in array
    for i in $n_procs; do
        ./procs[${i}] &
        pids[${i}]=$!
    done
    
    # wait for all pids
    for pid in ${pids[*]}; do
        wait $pid
    done
    
  • 17

    http://jeremy.zawodny.com/blog/archives/010717.html

    #!/bin/bash
    
    FAIL=0
    
    echo "starting"
    
    ./sleeper 2 0 &
    ./sleeper 2 1 &
    ./sleeper 3 0 &
    ./sleeper 2 0 &
    
    for job in `jobs -p`
    do
    echo $job
        wait $job || let "FAIL+=1"
    done
    
    echo $FAIL
    
    if [ "$FAIL" == "0" ];
    then
    echo "YAY!"
    else
    echo "FAIL! ($FAIL)"
    fi
    
  • 5

    如果你安装了GNU Parallel,你可以这样做:

    # If doCalculations is a function
    export -f doCalculations
    seq 0 9 | parallel doCalculations {}
    

    GNU Parallel将为您提供退出代码:

    • 0 - 所有作业都运行无误 .

    • 1-253 - 部分工作失败 . 退出状态提供失败作业的数量

    • 254 - 超过253个职位失败 .

    • 255 - 其他错误 .

    观看介绍视频以了解更多信息:http://pi.dk/1

  • 3

    到目前为止,'s what I'已经提出来了 . 我想看看如果一个孩子终止,如何中断睡眠命令,这样就不必将 WAITALL_DELAY 调整为一个人的用法 .

    waitall() { # PID...
      ## Wait for children to exit and indicate whether all exited with 0 status.
      local errors=0
      while :; do
        debug "Processes remaining: $*"
        for pid in "$@"; do
          shift
          if kill -0 "$pid" 2>/dev/null; then
            debug "$pid is still alive."
            set -- "$@" "$pid"
          elif wait "$pid"; then
            debug "$pid exited with zero exit status."
          else
            debug "$pid exited with non-zero exit status."
            ((++errors))
          fi
        done
        (("$#" > 0)) || break
        # TODO: how to interrupt this sleep when a child terminates?
        sleep ${WAITALL_DELAY:-1}
       done
      ((errors == 0))
    }
    
    debug() { echo "DEBUG: $*" >&2; }
    
    pids=""
    for t in 3 5 4; do 
      sleep "$t" &
      pids="$pids $!"
    done
    waitall $pids
    
  • 397

    怎么样简单:

    #!/bin/bash
    
    pids=""
    
    for i in `seq 0 9`; do
       doCalculations $i &
       pids="$pids $!"
    done
    
    wait $pids
    
    ...code continued here ...
    

    Update:

    正如多个评论者指出的那样,上面等待所有进程在继续之前完成,但如果其中一个失败则不会退出和失败,可以使用@Bryan,@ SamBrightman和其他人建议的以下修改来完成:

    #!/bin/bash
    
    pids=""
    RESULT=0
    
    
    for i in `seq 0 9`; do
       doCalculations $i &
       pids="$pids $!"
    done
    
    for pid in $pids; do
        wait $pid || let "RESULT=1"
    done
    
    if [ "$RESULT" == "1" ];
        then
           exit 1
    fi
    
    ...code continued here ...
    
  • 1

    这是使用 wait 的简单示例 .

    运行一些流程:

    $ sleep 10 &
    $ sleep 10 &
    $ sleep 20 &
    $ sleep 20 &
    

    然后使用 wait 命令等待它们:

    $ wait < <(jobs -p)
    

    或者只是等待(没有参数) .

    这将等待后台中的所有作业完成 .

    如果提供了-n选项,则等待下一个作业终止并返回其退出状态 .

    有关语法,请参阅: help waithelp jobs .

    但缺点是,这将仅返回最后一个ID的状态,因此您需要检查每个子进程的状态并将其存储在变量中 .

    或者让你的计算函数在失败时创建一些文件(空或失败日志),然后检查该文件是否存在,例如

    $ sleep 20 && true || tee fail &
    $ sleep 20 && false || tee fail &
    $ wait < <(jobs -p)
    $ test -f fail && echo Calculation failed.
    
  • 7

    我需要这个,但目标进程不是当前shell的子进程,在这种情况下 wait $PID 不起作用 . 我找到了以下替代方案:

    while [ -e /proc/$PID ]; do sleep 0.1 ; done
    

    这取决于 procfs 的存在,这可能不可用(例如,Mac不提供它) . 因此,为了便于携带,您可以使用它:

    while ps -p $PID >/dev/null ; do sleep 0.1 ; done
    
  • 260

    诱捕CHLD信号可能不起作用,因为如果它们同时到达,您可能会丢失一些信号 .

    #!/bin/bash
    
    trap 'rm -f $tmpfile' EXIT
    
    tmpfile=$(mktemp)
    
    doCalculations() {
        echo start job $i...
        sleep $((RANDOM % 5)) 
        echo ...end job $i
        exit $((RANDOM % 10))
    }
    
    number_of_jobs=10
    
    for i in $( seq 1 $number_of_jobs )
    do
        ( trap "echo job$i : exit value : \$? >> $tmpfile" EXIT; doCalculations ) &
    done
    
    wait 
    
    i=0
    while read res; do
        echo "$res"
        let i++
    done < "$tmpfile"
    
    echo $i jobs done !!!
    
  • 2

    为了并行化......

    for i in $(whatever_list) ; do
       do_something $i
    done
    

    把它翻译成这个......

    for i in $(whatever_list) ; do echo $i ; done | ## execute in parallel...
       (
       export -f do_something ## export functions (if needed)
       export PATH ## export any variables that are required
       xargs -I{} --max-procs 0 bash -c ' ## process in batches...
          {
          echo "processing {}" ## optional
          do_something {}
          }' 
       )
    
    • If an error occurs 在一个进程中,它不会中断其他进程,而是 it will result in a non-zero exit code from the sequence as a whole .

    • 在任何特定情况下,导出函数和变量可能是必需的,也可能不是必需的 .

    • 您可以根据所需的并行度设置 --max-procs0 表示"all at once") .

    • GNU Parallel在用于代替 xargs 时提供了一些附加功能 - 但默认情况下并不总是安装 .

    • 本例中并不严格需要 for 循环,因为 echo $i 基本上只是重新生成 $(whatever_list 的输出 . 我只是认为使用 for 关键字可以更容易地看到发生了什么 .

    • Bash字符串处理可能令人困惑 - 我发现使用单引号最适合包装非平凡的脚本 .

    • 您可以轻松地中断整个操作(使用^ C或类似操作),unlike the the more direct approach to Bash parallelism .

    这是一个简化的工作示例......

    for i in {0..5} ; do echo $i ; done |xargs -I{} --max-procs 2 bash -c '
       {
       echo sleep {}
       sleep 2s
       }'
    
  • 1

    我看到这里列出了很多很好的例子,也想把它扔进去 .

    #! /bin/bash
    
    items="1 2 3 4 5 6"
    pids=""
    
    for item in $items; do
        sleep $item &
        pids+="$! "
    done
    
    for pid in $pids; do
        wait $pid
        if [ $? -eq 0 ]; then
            echo "SUCCESS - Job $pid exited with a status of $?"
        else
            echo "FAILED - Job $pid exited with a status of $?"
        fi
    done
    

    我使用非常类似于并行启动/停止服务器/服务的东西并检查每个退出状态 . 对我很有用 . 希望这可以帮助别人!

  • 4

    我不相信Bash的内置功能是可能的 .

    can 在孩子退出时收到通知:

    #!/bin/sh
    set -o monitor        # enable script job control
    trap 'echo "child died"' CHLD
    

    但是,没有明显的方法可以让孩子在信号处理程序中退出状态 .

    获得该子状态通常是较低级别POSIX API中 wait 系列函数的作用 . 不幸的是,Bash对此的支持是有限的 - 您可以等待一个特定的子进程(并获得其退出状态),或者您可以等待所有这些进程,并始终获得0结果 .

    看起来不可能做的是相当于 waitpid(-1) ,它阻塞直到任何子进程返回 .

  • 3

    如果任何doCalculations失败,以下代码将等待所有计算的完成并返回退出状态1 .

    #!/bin/bash
    for i in $(seq 0 9); do
       (doCalculations $i >&2 & wait %1; echo $?) &
    done | grep -qv 0 && exit 1
    
  • 0

    只需将结果存储在shell中,例如在一个文件中 .

    #!/bin/bash
    tmp=/tmp/results
    
    : > $tmp  #clean the file
    
    for i in `seq 0 9`; do
      (doCalculations $i; echo $i:$?>>$tmp)&
    done      #iterate
    
    wait      #wait until all ready
    
    sort $tmp | grep -v ':0'  #... handle as required
    
  • 5

    这是我的版本适用于多个pid,如果执行时间过长则记录警告,如果执行时间超过给定值,则停止子进程 .

    function WaitForTaskCompletion {
        local pids="${1}" # pids to wait for, separated by semi-colon
        local soft_max_time="${2}" # If execution takes longer than $soft_max_time seconds, will log a warning, unless $soft_max_time equals 0.
        local hard_max_time="${3}" # If execution takes longer than $hard_max_time seconds, will stop execution, unless $hard_max_time equals 0.
        local caller_name="${4}" # Who called this function
        local exit_on_error="${5:-false}" # Should the function exit program on subprocess errors       
    
        Logger "${FUNCNAME[0]} called by [$caller_name]."
    
        local soft_alert=0 # Does a soft alert need to be triggered, if yes, send an alert once 
        local log_ttime=0 # local time instance for comparaison
    
        local seconds_begin=$SECONDS # Seconds since the beginning of the script
        local exec_time=0 # Seconds since the beginning of this function
    
        local retval=0 # return value of monitored pid process
        local errorcount=0 # Number of pids that finished with errors
    
        local pidCount # number of given pids
    
        IFS=';' read -a pidsArray <<< "$pids"
        pidCount=${#pidsArray[@]}
    
        while [ ${#pidsArray[@]} -gt 0 ]; do
            newPidsArray=()
            for pid in "${pidsArray[@]}"; do
                if kill -0 $pid > /dev/null 2>&1; then
                    newPidsArray+=($pid)
                else
                    wait $pid
                    result=$?
                    if [ $result -ne 0 ]; then
                        errorcount=$((errorcount+1))
                        Logger "${FUNCNAME[0]} called by [$caller_name] finished monitoring [$pid] with exitcode [$result]."
                    fi
                fi
            done
    
            ## Log a standby message every hour
            exec_time=$(($SECONDS - $seconds_begin))
            if [ $((($exec_time + 1) % 3600)) -eq 0 ]; then
                if [ $log_ttime -ne $exec_time ]; then
                    log_ttime=$exec_time
                    Logger "Current tasks still running with pids [${pidsArray[@]}]."
                fi
            fi
    
            if [ $exec_time -gt $soft_max_time ]; then
                if [ $soft_alert -eq 0 ] && [ $soft_max_time -ne 0 ]; then
                    Logger "Max soft execution time exceeded for task [$caller_name] with pids [${pidsArray[@]}]."
                    soft_alert=1
                    SendAlert
    
                fi
                if [ $exec_time -gt $hard_max_time ] && [ $hard_max_time -ne 0 ]; then
                    Logger "Max hard execution time exceeded for task [$caller_name] with pids [${pidsArray[@]}]. Stopping task execution."
                    kill -SIGTERM $pid
                    if [ $? == 0 ]; then
                        Logger "Task stopped successfully"
                    else
                        errrorcount=$((errorcount+1))
                    fi
                fi
            fi
    
            pidsArray=("${newPidsArray[@]}")
            sleep 1
        done
    
        Logger "${FUNCNAME[0]} ended for [$caller_name] using [$pidCount] subprocesses with [$errorcount] errors."
        if [ $exit_on_error == true ] && [ $errorcount -gt 0 ]; then
            Logger "Stopping execution."
            exit 1337
        else
            return $errorcount
        fi
    }
    
    # Just a plain stupid logging function to replace with yours
    function Logger {
        local value="${1}"
    
        echo $value
    }
    

    例如,等待所有三个进程完成,如果执行时间超过5秒,则记录警告,停止执行时间超过120秒的所有进程 . 不要在失败时退出程序 .

    function something {
    
        sleep 10 &
        pids="$!"
        sleep 12 &
        pids="$pids;$!"
        sleep 9 &
        pids="$pids;$!"
    
        WaitForTaskCompletion $pids 5 120 ${FUNCNAME[0]} false
    }
    # Launch the function
    someting
    
  • 45

    如果您有bash 4.2或更高版本,则以下内容可能对您有用 . 它使用关联数组来存储任务名称及其“代码”以及任务名称及其pid . 我还内置了一个简单的速率限制方法,如果你的任务消耗大量的CPU或I / O时间并且你想要限制并发任务的数量,那么它可能会派上用场 .

    该脚本在第一个循环中启动所有任务,并在第二个循环中使用结果 .

    对于简单的情况,这有点矫枉过正,但它允许非常整洁的东西 . 例如,可以将每个任务的错误消息存储在另一个关联数组中,并在一切安定下来后打印它们 .

    #! /bin/bash
    
    main () {
        local -A pids=()
        local -A tasks=([task1]="echo 1"
                        [task2]="echo 2"
                        [task3]="echo 3"
                        [task4]="false"
                        [task5]="echo 5"
                        [task6]="false")
        local max_concurrent_tasks=2
    
        for key in "${!tasks[@]}"; do
            while [ $(jobs 2>&1 | grep -c Running) -ge "$max_concurrent_tasks" ]; do
                sleep 1 # gnu sleep allows floating point here...
            done
            ${tasks[$key]} &
            pids+=(["$key"]="$!")
        done
    
        errors=0
        for key in "${!tasks[@]}"; do
            pid=${pids[$key]}
            local cur_ret=0
            if [ -z "$pid" ]; then
                echo "No Job ID known for the $key process" # should never happen
                cur_ret=1
            else
                wait $pid
                cur_ret=$?
            fi
            if [ "$cur_ret" -ne 0 ]; then
                errors=$(($errors + 1))
                echo "$key (${tasks[$key]}) failed."
            fi
        done
    
        return $errors
    }
    
    main
    
  • 1

    我刚刚将脚本修改为后台并将进程并行化 .

    我做了一些实验(在Solaris上同时使用bash和ksh)并发现'wait'输出退出状态(如果它不为零),或者在没有提供PID参数时返回非零退出的作业列表 . 例如 .

    击:

    $ sleep 20 && exit 1 &
    $ sleep 10 && exit 2 &
    $ wait
    [1]-  Exit 2                  sleep 20 && exit 2
    [2]+  Exit 1                  sleep 10 && exit 1
    

    KSH:

    $ sleep 20 && exit 1 &
    $ sleep 10 && exit 2 &
    $ wait
    [1]+  Done(2)                  sleep 20 && exit 2
    [2]+  Done(1)                  sleep 10 && exit 1
    

    此输出将写入stderr,因此OPs示例的简单解决方案可能是:

    #!/bin/bash
    
    trap "rm -f /tmp/x.$$" EXIT
    
    for i in `seq 0 9`; do
      doCalculations $i &
    done
    
    wait 2> /tmp/x.$$
    if [ `wc -l /tmp/x.$$` -gt 0 ] ; then
      exit 1
    fi
    

    虽然这个:

    wait 2> >(wc -l)
    

    也将返回一个计数,但没有tmp文件 . 这也可以这种方式使用,例如:

    wait 2> >(if [ `wc -l` -gt 0 ] ; then echo "ERROR"; fi)
    

    但这并不比tmp文件IMO更有用 . 我找不到一个有用的方法来避免tmp文件,同时也避免在子shell中运行“等待”,这根本不起作用 .

  • 1

    我已经对此进行了研究,并结合了其他示例中的所有最佳部分 . 当任何后台进程退出时,此脚本将执行 checkpids 函数,并输出退出状态而不依赖于轮询 .

    #!/bin/bash
    
    set -o monitor
    
    sleep 2 &
    sleep 4 && exit 1 &
    sleep 6 &
    
    pids=`jobs -p`
    
    checkpids() {
        for pid in $pids; do
            if kill -0 $pid 2>/dev/null; then
                echo $pid is still alive.
            elif wait $pid; then
                echo $pid exited with zero exit status.
            else
                echo $pid exited with non-zero exit status.
            fi
        done
        echo
    }
    
    trap checkpids CHLD
    
    wait
    
  • -2
    #!/bin/bash
    set -m
    for i in `seq 0 9`; do
      doCalculations $i &
    done
    while fg; do true; done
    
    • set -m 允许您在脚本中使用fg&bg

    • fg ,除了将最后一个进程放在前台之外,还具有与前景进程相同的退出状态
      当任何 fg 以非零退出状态退出时,

    • while fg 将停止循环

    遗憾的是,当后台进程以非零退出状态退出时,这将无法处理 . (循环不会立即终止 . 它将等待先前的进程完成 . )

  • 34

    这个工作,应该是一个好的,如果不是比@HoverHell的答案更好!

    #!/usr/bin/env bash
    
    set -m # allow for job control
    EXIT_CODE=0;  # exit code of overall script
    
    function foo() {
         echo "CHLD exit code is $1"
         echo "CHLD pid is $2"
         echo $(jobs -l)
    
         for job in `jobs -p`; do
             echo "PID => ${job}"
             wait ${job} ||  echo "At least one test failed with exit code => $?" ; EXIT_CODE=1
         done
    }
    
    trap 'foo $? $$' CHLD
    
    DIRN=$(dirname "$0");
    
    commands=(
        "{ echo "foo" && exit 4; }"
        "{ echo "bar" && exit 3; }"
        "{ echo "baz" && exit 5; }"
    )
    
    clen=`expr "${#commands[@]}" - 1` # get length of commands - 1
    
    for i in `seq 0 "$clen"`; do
        (echo "${commands[$i]}" | bash) &   # run the command via bash in subshell
        echo "$i ith command has been issued as a background job"
    done
    
    # wait for all to finish
    wait;
    
    echo "EXIT_CODE => $EXIT_CODE"
    exit "$EXIT_CODE"
    
    # end
    

    当然,我已经在NPM项目中永久化了这个脚本,它允许你并行运行bash命令,对于测试非常有用:

    https://github.com/ORESoftware/generic-subshell

  • 0

    陷阱是你的朋友 . 您可以在许多系统中捕获ERR . 您可以捕获EXIT,或者在DEBUG上捕获每个命令后执行一段代码 .

    这除了所有标准信号之外 .

  • 4
    set -e
    fail () {
        touch .failure
    }
    expect () {
        wait
        if [ -f .failure ]; then
            rm -f .failure
            exit 1
        fi
    }
    
    sleep 2 || fail &
    sleep 2 && false || fail &
    sleep 2 || fail
    expect
    

    顶部的 set -e 使您的脚本在失败时停止 .

    如果任何子作业失败, expect 将返回 1 .

  • 2

    这里已经有很多答案,但我很惊讶似乎没有人建议使用数组......所以这就是我所做的 - 这可能对将来有些人有用 .

    n=10 # run 10 jobs
    c=0
    PIDS=()
    
    while true
    
        my_function_or_command &
        PID=$!
        echo "Launched job as PID=$PID"
        PIDS+=($PID)
    
        (( c+=1 ))
    
        # required to prevent any exit due to error
        # caused by additional commands run which you
        # may add when modifying this example
        true
    
    do
    
        if (( c < n ))
        then
            continue
        else
            break
        fi
    done 
    
    
    # collect launched jobs
    
    for pid in "${PIDS[@]}"
    do
        wait $pid || echo "failed job PID=$pid"
    done
    
  • 23

    我最近用过这个(感谢Alnitak):

    #!/bin/bash
    # activate child monitoring
    set -o monitor
    
    # locking subprocess
    (while true; do sleep 0.001; done) &
    pid=$!
    
    # count, and kill when all done
    c=0
    function kill_on_count() {
        # you could kill on whatever criterion you wish for
        # I just counted to simulate bash's wait with no args
        [ $c -eq 9 ] && kill $pid
        c=$((c+1))
        echo -n '.' # async feedback (but you don't know which one)
    }
    trap "kill_on_count" CHLD
    
    function save_status() {
        local i=$1;
        local rc=$2;
        # do whatever, and here you know which one stopped
        # but remember, you're called from a subshell
        # so vars have their values at fork time
    }
    
    # care must be taken not to spawn more than one child per loop
    # e.g don't use `seq 0 9` here!
    for i in {0..9}; do
        (doCalculations $i; save_status $i $?) &
    done
    
    # wait for locking subprocess to be killed
    wait $pid
    echo
    

    从那里可以轻松推断,并有一个触发器(触摸文件,发送信号)并更改计数标准(触摸计数文件,或其他)以响应该触发器 . 或者如果你只想要“任何”非零rc,只需从save_status中取消锁定即可 .

  • 6

    等待多个子进程并在其中任何一个退出非零状态代码时退出的解决方案是使用'wait -n'

    #!/bin/bash
    wait_for_pids()
    {
        for (( i = 1; i <= $#; i++ )) do
            wait -n $@
            status=$?
            echo "received status: "$status
            if [ $status -ne 0 ] && [ $status -ne 127 ]; then
                exit 1
            fi
        done
    }
    
    sleep_for_10()
    {
        sleep 10
        exit 10
    }
    
    sleep_for_20()
    {
        sleep 20
    }
    
    sleep_for_10 &
    pid1=$!
    
    sleep_for_20 &
    pid2=$!
    
    wait_for_pids $pid2 $pid1
    

    状态代码'127'用于不存在的进程,这意味着孩子可能已退出 .

  • 2

    在等待该过程之前,可能存在过程完成的情况 . 如果我们触发等待已经完成的进程,它将触发错误,如pid不是此shell的子进程 . 为避免这种情况,可以使用以下函数来查找过程是否完成:

    isProcessComplete(){
    PID=$1
    while [ -e /proc/$PID ]
    do
        echo "Process: $PID is still running"
        sleep 5
    done
    echo "Process $PID has finished"
    }
    
  • 3

    我认为并行运行作业并检查状态的最直接方法是使用临时文件 . 已经有几个类似的答案(例如Nietzche-jou和mug896) .

    #!/bin/bash
    rm -f fail
    for i in `seq 0 9`; do
      doCalculations $i || touch fail &
    done
    wait 
    ! [ -f fail ]
    

    上面的代码不是线程安全的 . 如果您担心上面的代码将与其自身同时运行,最好使用更独特的文件名,例如fail . $$ . 最后一行是满足要求:“当任何子进程以代码结束时返回退出代码1!= 0?”我在那里提出了额外的要求来清理 . 它可能是更清楚地写这样:

    #!/bin/bash
    trap 'rm -f fail.$$' EXIT
    for i in `seq 0 9`; do
      doCalculations $i || touch fail.$$ &
    done
    wait 
    ! [ -f fail.$$ ]
    

    这是一个类似的片段,用于从多个作业中收集结果:我创建一个临时目录,在单独的文件中记录所有子任务的输出,然后将它们转储以供审阅 . 这与问题并不完全匹配 - 我将其作为奖励投入:

    #!/bin/bash
    trap 'rm -fr $WORK' EXIT
    
    WORK=/tmp/$$.work
    mkdir -p $WORK
    cd $WORK
    
    for i in `seq 0 9`; do
      doCalculations $i >$i.result &
    done
    wait 
    grep $ *  # display the results with filenames and contents
    
  • 5

    我想也许可以运行doCalculations;在发送到后台的子shell中回显"$?" >> / tmp / acc,然后等待,然后/ tmp / acc将包含退出状态,每行一个 . 但是,我不知道附加到累加器文件的多个进程的任何后果 .

    以下是对此建议的试用:

    文件:doCalcualtions

    #!/bin/sh
    
    random -e 20
    sleep $?
    random -e 10
    

    档案:试试

    #!/bin/sh
    
    rm /tmp/acc
    
    for i in $( seq 0 20 ) 
    do
            ( ./doCalculations "$i"; echo "$?" >>/tmp/acc ) &
    done
    
    wait
    
    cat /tmp/acc | fmt
    rm /tmp/acc
    

    运行./try的输出

    5 1 9 6 8 1 2 0 9 6 5 9 6 0 0 4 9 5 5 9 8
    

相关问题