为啥 sudo 在 while 循环中使用时将阻塞命令更改为非阻塞命令?

Posted

技术标签:

【中文标题】为啥 sudo 在 while 循环中使用时将阻塞命令更改为非阻塞命令?【英文标题】:Why does sudo change a blocking command to a non-blocking command when used in a while-loop?为什么 sudo 在 while 循环中使用时将阻塞命令更改为非阻塞命令? 【发布时间】:2012-12-28 11:56:41 【问题描述】:

或者:如何防止 sudo 的 rsync 在 while 循环中无限触发? 因为这就是(感觉)正在发生的事情,我不明白。

我正在尝试设置一个手表来同步修改的文件,它工作正常。但是,一旦我将所需的sudo 引入rsync 命令,单个inotify 事件就会导致rsync 命令无限期地触发。

#!/usr/bin/env bash
inotifywait -m -r --format '%w%f' -e modify -e move -e create -e delete /var/test | while read line; do
    sudo rsync -ah --del --progress --stats --update "$line" "/home/test/" 
done

当您编辑文件时,rsync 进入快速射击模式。但是丢失sudo(当然要使用您有权访问的文件夹)并且脚本会按预期工作。

    这是为什么呢? 如何使用sudo 命令使其正常工作?

【问题讨论】:

当你应用 sudo 时,我怀疑 rsync 正在等待输入密码。这就是您认为 rsync 无限期运行的方式。您是否尝试过在命令提示符下将 sudo'ed rsync 作为独立命令运行?它要求输入密码吗?如果是,您可能需要使用 expect 命令自动输入密码。 该命令无需密码即可正常工作 - 我在 sudoersnopassword 中允许使用 rsync。该命令也可以正确执行,它会同步文件。但它会一遍又一遍地这样做,直到我破坏脚本。 啊!!有你的问题!问题是当您编辑任何文件时,大多数编辑器都会创建交换文件甚至更新时间戳。这会向“inotifywait”发出许多修改通知,您应该将“-e close_write”开关传递给inotifywait 命令。事实上,只是不要寻找修改。看,***.com/questions/10300835/… 不幸的是,这无关紧要。否则,此行为也会影响非 sudo 变体。此外,我还想监视创建、删除和移动。我正在使用echo test > test.txt 进行测试,这里没有临时文件或属性更改。 没错,echo 不会那样做。尝试“vim /var/test/a.txt”并在脚本运行时继续编辑它。每当您在 vim 中按 enter 时,您都会看到 rsync 正在运行。没有? 【参考方案1】:

我有答案,通过实验找到的。但我不知道为什么会这样。请有人告诉我为什么 sudo 在这个循环中会破坏预期的阻塞行为。

由于sudo 破坏了脚本,我们可以通过使用包装器与sudo 保持距离:这是正确的:

inotifywait -m -r --format '%w%f' -e modify /var/test | while read line; do
    sh -c 'sudo rsync -ah "$line" "/home/test/"'
done

奇怪的是:将sudo 从包装器中拉出来,我们又遇到了旧的错误行为。很奇怪。这是错误的:

inotifywait -m -r --format '%w%f' -e modify /var/test | while read line; do
    sudo sh -c 'rsync -ah "$line" "/home/test/"'
done

【讨论】:

以上是关于为啥 sudo 在 while 循环中使用时将阻塞命令更改为非阻塞命令?的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用while循环时将值附加到字典中的列表?

为啥在链表中查找循环时将指针增加 2,为啥不增加 3、4、5?

没有 while(true) 循环的 C# 非阻塞套接字

为啥这个while循环在Python中永远不会停止

如何关闭在while循环中的线程中侦听的阻塞套接字?

为啥我的 while 循环中的条件在 python 中不起作用?