如何为特定命令生成一个进程并在其运行时捕获其输出?
例如,我想dd
在一个块上执行操作,当它执行其工作并生成状态消息时,我会使用 dd 进度的输出执行其他操作。我厌倦了下面的脚本,但它永远不会停止打印:
#!/bin/bash
data=$(dd if=/dev/urandom of=/dev/null bs=4096 count=32768 status=progress)&
while [ -z "$data" ]; do
echo "waiting for data..." "${data}"
# Do something else while $data is not returned
sleep 0.1
done
我已经取得了一些进步,但仍然不是我想要的。
#! /bin/bash
varFileDone=$(mktemp)
varFileOutput=$(mktemp)
dd if=/dev/urandom of=/dev/null bs=4096 \
count=32768 status=progress 2<&1 >> $varFileOutput && echo 1 > $varFileDone &
pid=$(pidof dd)
while [[ ! -s $varFileDone ]];
do
data=$(cat $varFileOutput)
echo "----->" "$data"
if [[ -s $data ]];
then
echo "we have data"
echo $data | cut -d"," -f3
else
echo "no data yet!"
fi
sleep 0.2
done
答案1
你的问题有点模糊。在异步环境中设置变量的使用在这里不太有效,因为变量的值永远不可用于原始环境。
使用 & 符号的异步调用&
可以替换为coproc
。我建议查看 bash 的手册页,因为有一些工具采用这种格式。
使用示例:
#!/bin/bash
coproc COPROC ($(dd if=/dev/urandom of=/dev/null bs=4096 count=32768))
while [[ $COPROC ]]; do
sleep 0.1
echo waiting!
done
wait # unnecessary, but proves the asynchronous processes are actually complete
echo "Task done!"
答案2
你可以尝试:
dd if=/dev/urandom of=/dev/null bs=4096 count=32768 & 2>&1 > /tmp/tmp
pid=$(ps|grep dd|awk '{print $1}')
while [[ ! "" = "$pid" ]]
do
# Do something else while dd is still writing
grep "," /tmp/tmp | grep -v "+"|awk '{$2" "$3}'
done
答案3
如果你不想看到dd
命令输出,你可以添加一个重定向,如下所示:
data=$(dd if=/dev/urandom of=/dev/null bs=4096 count=32768 2>&1 /dev/null)
2>&1
用于重定向输出 AND 错误。
只需修改您想要的输出(替换/dev/null
为任何其他文件)。您可以使用tail
命令检查该过程中生成的输出,即tail -f /your/output/file
。