Linux Shell 脚本:如何检测 NFS 挂载点(或服务器)已死?

Posted

技术标签:

【中文标题】Linux Shell 脚本:如何检测 NFS 挂载点(或服务器)已死?【英文标题】:Linux Shell Script: How to detect NFS Mount-point (or the Server) is dead? 【发布时间】:2013-07-12 09:44:12 【问题描述】:

一般在 NFS 客户端,如何使用 Bash Shell 脚本检测Mounted-Point is no more available or DEAD from Server-end

通常我会这样做:

if ls '/var/data' 2>&1 | grep 'Stale file handle';
then
   echo "failing";
else
   echo "ok";
fi

但问题是,特别是当 NFS 服务器完全死机或停止时,即使在客户端进入该目录的 ls 命令也会被挂起或死机。意味着,上面的脚本不再可用。

请问有什么办法可以再次检测到吗?

【问题讨论】:

【参考方案1】:

“stat”命令是一种更简洁的方式:

statresult=`stat /my/mountpoint 2>&1 | grep -i "stale"`
if [ "$statresult" != "" ]; then
  #result not empty: mountpoint is stale; remove it
  umount -f /my/mountpoint
fi

另外,您可以使用rpcinfo来检测远程nfs共享是否可用:

rpcinfo -t remote.system.net nfs > /dev/null 2>&1
if [ $? -eq 0 ]; then
  echo Remote NFS share available.
fi

添加于 2013-07-15T14:31:18-05:00:

我进一步研究了这一点,因为我还在编写一个需要识别陈旧挂载点的脚本。受one of the replies 的启发,“有没有一种好方法可以检测过时的 NFS 挂载”,我认为以下可能是检查 bash 中特定挂载点是否过时的最可靠方法:

read -t1 < <(stat -t "/my/mountpoint")
if [ $? -eq 1 ]; then
   echo NFS mount stale. Removing... 
   umount -f -l /my/mountpoint
fi

如果 stat 命令由于某种原因挂起,“read -t1”构造可靠地超时子shell。

添加于 2013-07-17T12:03:23-05:00:

虽然read -t1 &lt; &lt;(stat -t "/my/mountpoint") 有效,但似乎没有办法在挂载点过时时将其错误输出静音。在子shell 中或在命令行末尾添加&gt; /dev/null 2&gt;&amp;1 会破坏它。使用简单的测试:if [ -d /path/to/mountpoint ] ; then ... fi 也可以工作,并且在脚本中可能更可取。经过多次测试,这就是我最终使用的。

添加于 2013-07-19T13:51:27-05:00:

对我的问题“How can I use read timeouts with stat?”的回复提供了有关在目标不可用且命令挂起几分钟后自行超时时静音 stat(或 rpcinfo)输出的更多详细信息。虽然[ -d /some/mountpoint ] 可用于检测陈旧的挂载点,但rpcinfo 没有类似的替代方案,因此使用read -t1 重定向是最佳选择。子shell 的输出可以用2>&- 静音。以下是来自CodeMonkey's response 的示例:

mountpoint="/my/mountpoint"
read -t1 < <(stat -t "$mountpoint" 2>&-)
if [[ -n "$REPLY" ]]; then
  echo "NFS mount stale. Removing..."
  umount -f -l "$mountpoint"
fi

也许现在这个问题已经完全回答了:)。

【讨论】:

我在我的脚本 nfs_automount、now available on GitHub 中使用了过时的 NFS 挂载点检测。 不错的答案。我看到read -t1 &lt; &lt;(stat -t "$MOUNT_DIR" 2&gt;&amp;-) 提供了142 的返回值。所以将[ ! $? -eq 0 ] 作为测试可能会更好。 另一点:read -t1 &lt; &lt;(stat -t "$mountpoint" 2&gt;&amp;-) 会为挂载的文件夹留下一个打开的文件句柄(或类似的句柄)。因此,如果您不使用 -l 标志,挂载选项将失败。您可以改用timeout 1 stat -t "$mountpoint" &gt; /dev/null。这将杀死 stat 命令并因此杀死它的打开文件句柄。【参考方案2】:

Ville 和 CodeMonkey 给出的最终答案几乎是正确的。我不确定没有人注意到这一点,但是 $REPLY 字符串有内容是成功的,而不是失败。因此,empty $REPLY 字符串表示挂载已过时。因此,条件应该使用-z,而不是-n:

mountpoint="/my/mountpoint"
read -t1 < <(stat -t "$mountpoint" 2>&-)
if [ -z "$REPLY" ] ; then
  echo "NFS mount stale. Removing..."
  umount -f -l "$mountpoint"
fi

我已经使用有效和无效的挂载点多次运行它,它可以工作。 -n 检查给了我相反的结果,当它绝对有效时,它表明安装是陈旧的。

此外,简单的字符串检查不需要双括号。

【讨论】:

【参考方案3】:

使用“-z”我得到一个过时的 NFS,但它完全错误,我可以访问它并读写文件

【讨论】:

嗨,欢迎来到 ***!如果您在回答任何问题之前可以read these guidelines,那就太好了。谢谢。

以上是关于Linux Shell 脚本:如何检测 NFS 挂载点(或服务器)已死?的主要内容,如果未能解决你的问题,请参考以下文章

Linux shell脚本入门

linux服务器挂掉自动重启脚本(转)

DAY-10 Linux基础及shell脚本

Linux系统shell脚本之监控httpd服务

linux shell脚本检测硬盘磁盘空间 邮件报警

Linux如何使用shell命令检测PHP木马防止脚本木马的破坏