1

我正在尝试在 bash 脚本中实现动态进度条,这是我们在安装新软件包时看到的那种。为了做到这一点,随机任务将调用进度条脚本作为后台任务,并为其提供一些整数值。

第一个脚本使用管道来提供第二个脚本。

#!/bin/bash
# randomtask

pbar_x=0            # percentage of progress
pbar_xmax=100

while [[ $pbar_x != $pbar_xmax ]]; do
    echo "$pbar_x"
    sleep 1
done | ./progressbar &

# do things
(( pbar_x++ ))

# when task is done
(( pbar_x = pbar_xmax ))

因此,第二个脚本需要不断地接收整数并打印出来。

#!/bin/bash
# progressbar

while [ 1 ]; do
    read x
    echo "progress: $x%"
done

但是在这里,第二个脚本在更新时不会收到这些值。我做错什么了 ?

4

2 回答 2

0

那行不通,while循环在子进程中运行,主程序的更改不会以任何方式影响它。

有几种IPC机制,这里我使用命名管道(FIFO):

pbar_x=0            # percentage of progress
pbar_xmax=100
pipename="mypipe"

# Create the pipe 
mkfifo "$pipename"

# progressbar will block waiting on input
./progressbar < "$pipename" &

while (( pbar_x != pbar_xmax )); do
     #do things
     (( pbar_x++ ))
     echo "$pbar_x"
     sleep 1
     # when task is done
     #(( pbar_x = pbar_xmax ))
done > "$pipename"

rm "$pipename"

我还修改了progressbar

# This exits the loop when the pipe is closed
while read x
do
    echo "progress: $x%"
done

使用第三个脚本,您可以改用进程替换

于 2018-01-14T16:51:21.690 回答
0

我在 WSL 上,这意味着我不能使用 mkfifo。coproc 似乎完美地满足了我的需求,所以我搜索并最终找到了这个: coproc usage with exemples [bash-hackers wiki]

我们开始这个过程coproc并将其输出重定向到stdout

{ coproc PBAR { ./progressbar; } >&3; } 3>&1

然后我们可以通过文件描述符 ${PBAR[0]}(输出)和 ${PBAR[1]}(输入)访问它的输入和输出

    echo "$pbar_x" >&"${PBAR[1]}"

随机任务

#!/bin/bash

pbar_x=0            # percentage of progress
pbar_xmax=100

{ coproc PBAR { ./progressbar; } >&3; } 3>&1

while (( pbar_x <= 10)); do
    echo $(( pbar_x++ )) >&"${PBAR[1]}"
    sleep 1
done

# do things
echo $(( pbar_x++ )) >&"${PBAR[1]}"

# when task is done
echo $(( pbar_x = pbar_xmax )) >&"${PBAR[1]}"

进度条

#!/bin/bash

while read x; do
    echo "progress: $x%"
done

请注意:

POSIX(R) 未指定 coproc 关键字。

coproc 关键字出现在 Bash 4.0-alpha 版中

于 2018-01-17T17:30:38.967 回答