0

这背后的一点历史 - 我正在尝试编写一个 nagios 插件来检测是否已卸载 nfs 挂载以及挂载是否过时,这就是我遇到问题的地方。

我想要实现的是检测安装是否过时。我要解决的问题是陈旧的 nfs 句柄会导致对该目录的任何操作在 3-4 分钟后挂起并超时。通过使用读取强制在 nfs 挂载目录中的 stat 命令超时,我应该能够解决该问题。

所以我在某个地方找到了这个片段,当从 nfs 客户端上的 cli 手动运行时,它可以完美运行(其中 /www/logs/foo 是一个陈旧的 nfs 挂载)

$ read -t 2 < <(stat -t /www/logs/foo/*); echo $?
1

当我尝试将此代码段合并到这样的脚本中时,问题就来了(附加了代码段,最后附加了完整的脚本):

list_of_mounts=$(grep nfs /etc/fstab | grep -v ^# | awk '{print $2'} | xargs)
exitstatus $LINENO

for X in $list_of_mounts; do
    AM_I_EXCLUDED=`echo " $* " | grep " $X " -q; echo $?`
    if [ "$AM_I_EXCLUDED" -eq "0" ]; then
    echo "" >> /dev/null
    #check to see if mount is mounted according to /proc/mounts
    elif [ ! `grep --quiet "$X " /proc/mounts; echo $?` -eq 0 ]; then
        #mount is not mounted at all, add to list to remount
        remount_list=`echo $remount_list $X`;
    #now make sure its not stale
    elif [ ! "`read -t 2  < <(stat -t $X/*) ; echo $?`" -eq "0" ]; then
        stalemount_list=`echo $stalemount_list $X`
    fi

给我这个错误:

/usr/lib64/nagios/plugins/check_nfs_mounts.sh: command substitution: line 46: syntax error near unexpected token `<'
/usr/lib64/nagios/plugins/check_nfs_mounts.sh: command substitution: line 46: `read -t 2  < <( '
/usr/lib64/nagios/plugins/check_nfs_mounts.sh: command substitution: line 46: syntax error near unexpected token `)'
/usr/lib64/nagios/plugins/check_nfs_mounts.sh: command substitution: line 46: ` ) ; echo $?'
/usr/lib64/nagios/plugins/check_nfs_mounts.sh: line 46: [: stat -t /www/logs/foo/*: integer expression expected

我能够通过使用“read -t 2<<< $(stat -t $X/ )”而不是“read -t 2<<(stat -t $X /)”来解决语法错误,但是 stat不再受益于读取​​超时,这让我回到了原来的问题。

虽然我对新的解决方案持开放态度,但我也很好奇什么行为可能导致这种 shell 与脚本的差异。

完整的 nagios 检查:

#!/bin/bash

usage() {
    echo "
    Usage:
    check_nfs_mounts.sh
    It just works.
    Optional: include an argument to exclude that mount point
"
}
ok() {
        echo "OK - $*"; exit 0
        exit
}
warning() {
        echo "WARNING - $*"; exit 1
        exit
}
critical() {
        echo "CRITICAL - $*"; exit 2
        exit
}
unknown() {
        echo "UNKNOWN - $*"; exit 3
        exit
}
exitstatus() {
        if [ ! "$?" -eq "0" ] ;
        then unknown "Plugin failure - exit code not OK - error line $*"
        fi
}
# Get Mounts
list_of_mounts=$(grep nfs /etc/fstab | grep -v ^# | awk '{print $2'} | xargs)
exitstatus $LINENO

for X in $list_of_mounts; do
    AM_I_EXCLUDED=`echo " $* " | grep " $X " -q; echo $?`
    if [ "$AM_I_EXCLUDED" -eq "0" ]; then
    echo "" >> /dev/null
    #check to see if mount is mounted according to /proc/mounts
    elif [ ! `grep --quiet "$X " /proc/mounts; echo $?` -eq 0 ]; then
        #mount is not mounted at all, add to list to remount
        remount_list=`echo $remount_list $X`;
    #now make sure its not stale
    elif [ ! "`read -t 2  <<< $(stat -t $X/*) ; echo $?`" -eq "0" ]; then
        stalemount_list=`echo $stalemount_list $X`
    fi
done
#Make sure result is a number
if [ -n "$remount_list" ] && [ -n "$stalemount_list" ];  then
    critical "Not mounted: $remount_list , Stale mounts: $stalemount_list"
elif [ -n "$remount_list" ] && [ -z "$stalemount_list"]; then
    critical "Not mounted: $remount_list"
elif [ -n "$stalemount_list" ] && [ -n "$remount_list" ]; then
    critical "Stale mount: $stalemount_list"
elif [ -z "$stalemount_list" ] && [ -z "$remount_list" ]; then
    ok "All mounts mounted"
fi
4

2 回答 2

1

您需要确保您的 shebang 指定 Bash:

#!/bin/bash

错误消息的原因是在您的系统上,/bin/sh当没有 shebang 或它是#!/bin/sh.

在这种情况下,Bash 就像您启动它一样运行,bash --posix它禁用了一些非 POSIX 功能,例如进程替换 ( <()),但令人困惑的是,这里的字符串 ( <<<) 等其他功能却没有。

改变你的shebang,你应该没问题。

于 2012-06-20T11:36:57.313 回答
0

您可以通过这种方式保存子外壳的输出:

$ read a < <(echo one)
$ echo $a
one

或者以这种方式(如果您只想处理 $a 并忘记它:

$ ( echo one; echo two) | (read a; echo $a)
one

第一个变体仅适用于bash. Bourne Shell ( /bin/sh) 不支持此语法。可能这就是您收到错误消息的原因。可能是你的脚本/bin/sh不是由/bin/bash

于 2012-06-19T17:17:05.840 回答