我有一个脚本,该脚本使用SSH在远程服务器上运行命令。我想Remote:
在输出的每一行前添加字符串,但是我不希望每行都延迟到整个行可用为止。这是我的命令的输出:
$ myproject-db-push my_database_name 从数据库导出...完成 存档数据...完成 将存档上传到远程...完成 在远程上运行安装脚本 远程:将存档解压缩到临时目录中...完成 远程:使用数据库:my_database_name 远程:删除集合: 远程:-my_collection_foo 远程:-my_collection_bar 远程:导入新数据...完成
在这种情况下,我使用的sed
是这样的:
echo "$INSTALLCMD" | ssh -T "deploy@$SERVER" | sed -u "s/^/Remote: /"
正如我所解释的,问题是没有分行打印到屏幕上。如果我删除| sed
零件,它会按预期工作。首先,这是这样写的:
导入新数据...
几秒钟后,该行完成了:
导入新数据...完成
我假设sed
只能逐行工作。我尝试将其设置为无缓冲,但它仍在等待整行。还有另一种方法可以做到这一点吗?
这是一个有点棘手,因为所有这些utillities( ,sed
,awk
)grep
的行缓冲。这意味着它们仅在行结束时(换行已结束)才打印输出。他们无法逐字符读取输入的字符。
因此,为了进行测试,我做了一个小的序列,该序列模拟了您的行为:
{
echo -n "first task: "
sleep 2
echo "done"
echo -n "second task: "
sleep 2
echo "done"
}
就像您的问题一样,它会first task:
在2秒钟后打印出来done
。您可以通过在终端中进行复制来自己尝试。
解决方案:
在命令后面添加以下内容:
IFS=
command | { x=1; while IFS= read -d'' -s -N 1 char; do
[ $x ] && printf "Remote: "
printf "$char"
unset x
[ "$char" == "
" ] && x=1
done; }
解释:
的read
内置bash
可以逐字符读取输入的字符。该部分read -d'' -s -N 1 char
禁用定界符-d''
,激活静默模式,-s
并且一次仅读取1个字符-N 1
到变量中$char
。然后,该命令检查变量是否$x
存在。如果是,我们在新行中并打印“前缀”。然后打印字符。取消设置$x
。然后,最后一条语句检查字符是否为换行符。如果将换行符设置$x
为1
和,则在下一个循环中,将打印“前缀”。
当您同时包含两个序列时,可以测试整个事情:
{
echo -n "first task: "
sleep 2
echo "done"
echo -n "second task: "
sleep 2
echo "done"
} | { x=1; while IFS= read -d'' -s -N 1 char; do
[ $x ] && printf "Remote: "
printf "$char"
unset x
[ "$char" == "
" ] && x=1
done; }
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句