除了我之前关于shell脚本中多线程的查询 我很好奇是否有可能有多个进度条。
以下是我预期结果的代码段:
Output : 1 of 100 Files Completed # Thread1
Output : 10 of 45 files Completed # Thread 2
更新了显示进度的行。是否可以实现它shell。 如果有人对此有所了解,请感谢您的帮助。
此致 基兰
答案 0 :(得分:2)
是的,这是非常有可能的。
假设您现有的代码(基于您之前的帖子)目前是这样的:
do_something() {
...
echo -ne "\r$index of $No_of_Files Completed"
...
}
do_something A &
do_something B &
do_something C &
wait
...然后你可以进行以下调整,以达到你想到的效果:
# Background tasks will no longer write directly to the console; instead,
# they will write to temporary files which will be read periodically
# by a special log printer task (which will display everything nicely.)
#
# Name of temporary files
STATUS_BASENAME="/tmp/~$$.status"
# Process IDs of backgrounded tasks; we record them so we can wait on them
# specifically but not wait on the special log printer task
TASK_PIDS=""
do_something() {
# First parameter must be a task ID starting at 0 incremented by 1
TASK_ID=$1 ; shift
...
# We write new status to status file (note we don't echo -n, we want that
# trailing newline)
# Try to go through a temporary status file which we rename afterwards to
# avoid race conditions with the special log printer task
echo "$x of 5 Completed" >"${STATUS_BASENAME}.${TASK_ID}.tmp"
mv "${STATUS_BASENAME}.${TASK_ID}.tmp" "${STATUS_BASENAME}.${TASK_ID}"
...
}
# Special log printer task
status_printer() {
# First time in the loop is special insofar we don't have to
# scroll up to overwrite previous output.
FIRST_TIME=1
while true ; do
# If not first time, scroll up as many lines as we have
# regular background tasks to overwrite previous output.
test $FIRST_TIME -eq 0 && for PID in $TASK_PIDS ; do
echo -ne '\033M' # scrol up one line using ANSI/VT100 cursor control sequences
done
FIRST_TIME=0
TASK_ID=0
for PID in $TASK_PIDS ; do
# If status file exists print first line
test -f "${STATUS_BASENAME}.${TASK_ID}" && head -1 "${STATUS_BASENAME}.${TASK_ID}" || echo "waiting..."
TASK_ID=`expr $TASK_ID + 1` # using expr for portability :)
done
test -f "${STATUS_BASENAME}.done" && return
sleep 1 # seconds to wait between updates
done
}
do_something 0 A &
TASK_PIDS="$TASK_PIDS $!"
do_something 1 B &
TASK_PIDS="$TASK_PIDS $!"
do_something 2 C &
TASK_PIDS="$TASK_PIDS $!"
status_printer &
PRINTER_PID=$!
# Wait for background tasks
wait $TASK_PIDS
# Stop special printer task instead of doing just
# kill $PRINTER_PID >/dev/null
touch "${STATUS_BASENAME}.done"
wait $PRINTER_PID
# Cleanup
rm -f "${STATUS_BASENAME}."*
答案 1 :(得分:1)
像pv -c
那样做什么?
当然,请参阅src/pv/cursor.c。虽然它只能从shell中安全地实现,但是一个小的C实用程序可以处理它。
答案 2 :(得分:0)
如果您的子进程输出是可过滤的,那么您可以将每个子进程的stdout重定向到不同的文件描述符,然后调用一个函数来遍历该文件描述符的输出。然后,您可以尝试使用printf更新进度表。这是你遇到麻烦的地方。不确定Bash的内置printf可以处理该终端的详细信息。我从未尝试在Bash中编写一个进行多行输出的进度表。为什么不使用对话框?