显示 for 循环启动后的进度

显示 for 循环启动后的进度

for我在交互式会话中开始循环bash。对于这个问题,我们可以假设循环是这样的

for i in dir/*; do
    program "$i"
done > log

该命令花费的时间比预期长得多,但仍然运行。如何查看当前运行for循环的进度。

非解决方案:

  • 看着log
    不起作用,因为: program预计会安静地运行。您可以将其视为program验证者。如果循环完成而没有任何输出,那么我很高兴。
  • 停止循环。添加某种进度指示(例如echo "$i")。再次开始循环。
    不起作用,因为:该循环已经运行了几个小时。我不想浪费当前投入的所有时间和精力。我认为一切正常。我只是好奇,想知道目前的进展。
  • Ctrl+Z然后set -x; fg
    不起作用,因为: bash使用时不继续循环fg。只有循环内的当前/下一个命令运行后fg,循环才会退出。您可以使用 自己尝试一下for i in {1..200}; do printf '%s ' $i; /usr/bin/sleep 0.5; done

答案1

通配符dir/*始终以相同的顺序扩展。此功能与当前值一起$i可用于显示进度信息。

$i可以通过查看系统上运行的进程来检索 的当前值。这以下命令打印当前运行的实例program及其参数。
如果有多个program进程,您可能需要使用--parent ...选项来仅匹配由运行要检查的循环 pgrep的 shell 启动的进程。for

ps -o args= -fp $(pgrep program)

手动提取 的值$i,然后使用获取进度

a=(dir/*)
n=$(printf %s\\0 "${a[@]}" | grep -zFxnm1 'the exact value of $i' | cut -f1 -d:) 
echo "Progress: $n / ${#a[@]}"

这在两个假设下有效

  1. dir/运行循环时的内容不会改变。如果program创建、重命名或删除文件,则数字可能是错误的。

  2. 调用program开始一个新的进程。如果program是一个bash函数,则 不会有子流程program。如果函数function本身调用另一个启动新进程的程序,那么您可以查找该子程序。但是,如果program是 bash 内置函数(由 列出的命令help)或纯 bash 函数(仅使用bash内置函数),那么您就不走运了。

如果您遇到问题 2 或者您的for循环具有与问题中的结构不同的结构(例如,program < "$1"或者具有许多不同程序的非常长的循环体),那么您可能可以lsof通过查看由您当前的 shell 会话或其子进程。

相关内容