bash 中具有共享变量的多进程
Multiprocess with shared variable in bash
我正在尝试在 bash 脚本中实现动态进度条,即我们在安装新包时看到的那种。为了做到这一点,randomtask 将调用 progressbar 脚本作为后台任务并为其提供一些整数值。
第一个脚本使用管道来提供第二个脚本。
#!/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
但是在这里,第二个脚本在更新时没有收到值。我做错了什么?
那不行,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
使用第三个脚本,您可以使用 进程替换。
我在使用 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
请注意:
The coproc keyword is not specified by POSIX(R).
The coproc keyword appeared in Bash version 4.0-alpha
我正在尝试在 bash 脚本中实现动态进度条,即我们在安装新包时看到的那种。为了做到这一点,randomtask 将调用 progressbar 脚本作为后台任务并为其提供一些整数值。
第一个脚本使用管道来提供第二个脚本。
#!/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
但是在这里,第二个脚本在更新时没有收到值。我做错了什么?
那不行,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
使用第三个脚本,您可以使用 进程替换。
我在使用 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
请注意:
The coproc keyword is not specified by POSIX(R).
The coproc keyword appeared in Bash version 4.0-alpha