如何在一定条件下使用管道?

如何在一定条件下使用管道?

我想在 grep 找到或未找到某些内容时进行循环,我可以这样写:

while grep 'matches' inLogFile.txt
do
  echo good.
  sleep 10
done

或者

while grep -v 'notHereYet' inLogFile.txt
do
  sleep 2
done
echo -e '\a'Yo! It is here now.

我在交互式 shell 提示符下输入这些内容。

所以我想反复检查df卷的实际安装时间,有点像:

while df | grep -v '/toBeMounted'
do
  sleep 2
done
echo -e '\a'Hey, I think you wanted to know that /toBeMounted is available finally.

我无法弄清楚如何将管道分组到条件中。

我知道我可以做类似的事情:

while [ -z "$(df|grep '/toBeMounted')" ]
do
  sleep 2
done
echo -e '\a'Okay that is finally present now.

但我觉得应该有一种方法可以使用退出值而不是字符串比较来做到这一点。

答案1

为了使逻辑正确,只需进行微小的更改。使用:

while ! df | grep '/toBeMounted'
do
  sleep 2
done
echo -e '\a'Hey, I think you wanted to know that /toBeMounted is available finally.

讨论

问题中对应的代码是:

while df | grep -v '/toBeMounted'

管道的退出代码是管道中最后一个命令的退出代码。 grep -v '/toBeMounted'如果至少有一行输入不匹配/toBeMounted,则返回 true (code=0)。因此,这会测试除了之外是否还挂载了其他东西/toBeMounted这根本不是您想要的。

要使用dfgrep测试是否/toBeMounted已安装,我们需要

df | grep '/toBeMounted'

如果已安装,则返回 true /toBeMounted。您实际上需要的是对此的否定:您需要一个条件,如果 /toBeMounted未安装,则为 true。为此,我们只需要使用否定,表示为!

! df | grep '/toBeMounted'

这就是我们在上面的代码中使用的。

文档

Bash 手册

管道的返回状态是最后一个命令的退出状态,除非启用了 pipefail 选项。如果启用了 pipefail,则管道的返回状态是最后一个(最右边)以非零状态退出的命令的值,如果所有命令都成功退出,则返回零。如果保留字 ! 位于管道之前,则该管道的退出状态是上述退出状态的逻辑否定。shell 等待管道中的所有命令终止,然后返回值。

答案2

df您正在使用的事实grep告诉我,您正在过滤输出,df直到某个设备安装到特定目录,即无论它是否在列表中。

无需过滤列表,只需关注所需的目录。幸运的是,该实用程序mountpoint允许我们这样做,并允许处理该命令的退出状态。考虑一下:

$ mountpoint  /mnt/HDD/                                                        
/mnt/HDD/ is a mountpoint
$ echo $?
0
$ mountpoint  ~                                                                
/home/xieerqi is not a mountpoint
$ echo $?
1

因此,您的脚本可以重写为

while ! mountput /toBeMounted > /dev/null
do
   sleep 3
done
echo "Yup, /toBeMounted got mounted!"

使用我自己的磁盘运行示例:

$ while ! mountpoint /mnt/HDD > /dev/null
> do 
>     echo "Waiting"
>     sleep 1
> done && echo "/mnt/HDD is mounted"
Waiting
Waiting
Waiting
Waiting
Waiting
/mnt/HDD is mounted

附注:你可以相当轻松地实现自己的mountpoint命令版本,例如,在 python 中,就像我所做的那样:

#!/usr/bin/env python3
from os import path
import sys

def main():

    if not sys.argv[1]:
       print('Missing a path')
       sys.exit(1)

    full_path = path.realpath(sys.argv[1])
    with open('/proc/self/mounts') as mounts:
       print
       for line in mounts:
           if full_path in line:
              print(full_path,' is mountpoint')
              sys.exit(0)
    print(full_path,' is not a mountpoint')
    sys.exit(1)

if __name__ == '__main__':
    main()

示例运行:

$ python3 ./is_mountpoint.py /mnt/HDD                                          
/mnt/HDD  is mountpoint
$ python3 ./is_mountpoint.py ~                                                 
/home/xieerqi  is not a mountpoint

相关内容