为什么在从yes读取的循环中丢失字节?

时间:2018-12-14 16:34:59

标签: bash

使用循环创建用户,提供默认密码,然后使密码过期,但是我的初稿用yes将密码插入其中,该密码破裂了。这似乎是很多任务的标准习语,所以我想更好地理解为什么要这样做:

$: yes defaultString | for u in "${tst[@]}"; do head -2; done
defaultString
defaultString
faultString
defaultString
ultString
defaultString

第一个之后的值被破坏了。我丢失的字节怎么了?

该代码实际使用passwd "$u" --stdin而不是head

yes $default | 
for u in "${tst[@]}"
do  useradd "$u"
    sudo passwd "$u" --stdin
    sudo passwd "$u" --expire
done

(易于修复-我将值放入临时文件中,每次都完整读取,但我仍然想更好地理解这一点。)

1 个答案:

答案 0 :(得分:3)

您正在使用的软件中实现性能优化(正如最初提出的问题,head):没有专门设计并故意仅消耗所需数量的stdin的程序(通常会消耗较大的内容(对于head的典型实现来说,容量约为2-8kb),然后根据需要解析行。

由于head消耗的内容多于发出的内容,因此内容介于两次调用之间。如果您不接受这种情况,则可以使用bash内置的read编写等效文件,该文件逐字节运行:

tst=( one two three )
writeTwoLines() { IFS= read -r line1; IFS= read -r line2; printf '%s\n' "$line1" "$line2"; }
yes defaultString | for u in "${tst[@]}"; do writeTwoLines; done

...正确发射:

defaultString
defaultString
defaultString
defaultString
defaultString
defaultString