【问题标题】:check remotely whether all files are present or not in linux?远程检查linux中是否所有文件都存在?
【发布时间】:2018-06-19 01:15:33
【问题描述】:

我有一个下面的脚本,它迭代所有机器并远程检查每台机器:

  • 特定目录是否存在?
  • 该目录中是否存在所有 2000 个文件。

下面是代码:

for machine in "${MACHINES[@]}"; do
   dircheck=($(ssh -o "StrictHostKeyChecking no" user@${machine} [[ ! -d "$dir3" ]] \&\& exit 1 \; ls -t1 "$dir3"))
   if [[ $? != 0 ]] ;then
       echo "Folder $dir3 doesn't exist on $machine" >&2
       exit 1
   fi

    # this is for checking all the 2000 files
    # this check is very slow when it checks all 2000 files
    for el in ${FILES[@]}
    do
        printf -v cmd '%q ' test -e "$dir3/process_${el}.log"
        ssh user@${machine} "$cmd" \
        || { echo "File number $el missing on $machine." >&2;
             exit 1; }
    done
done

现在的问题是检查所有 2000 个文件需要很多时间,所以想看看是否有任何方法我们仍然可以做同样的事情,但速度有点快?

更新:

所以总的来说我的脚本是这样的:

readonly MACHINES=(machineA machineB machineC)
readonly dir3=/some_path
echo $dir3
FILES=({0..1999})

checkFunc() {
  test -d "$dir3" || echo "NODIR"

  local filename successCount=0
  while IFS= read -r filename; do
    test -e "$dir3/process_${filename}.log" && (( ++successCount ))
  done
  printf '%s\n' "$successCount"
}

for machine in "${MACHINES[@]}"; do
    actual=$(
      printf '%s\0' "${FILES[@]}" | \
        ssh "$machine" "$(declare -p dir3; declare -f checkFunc); checkFunc"
    ) || { echo "ERROR: Unable to retrieve remote file count" >&2; exit 1; }

    case $actual in
      (${#FILES[@]}) echo "SUCCESS: Expected, and found, $numberOfActuallyRemoteFiles files" ;;
      (NODIR)        echo "FAILURE: Directory $dir3 does not exist" ;;
      (*)            echo "FAILURE: Out of ${#FILES[@]} files, only $actual exist" ;;
    esac
done

【问题讨论】:

  • 顺便说一句,array=( $(...) ) 通常来说是一种代码气味——除非你小心,否则它很容易在本地扩展看起来像 glob 的东西,和/或在文件名包含空格时将它们拆分为多个元素.几乎总是更适合做类似while IFS= read -r line; do array+=( "$line" ); done < <(...) 的事情; 尤其是如果您可以用 NUL 分隔您的流并因此使用 IFS= read -r -d '' line
  • SFTP 协议比普通 ssh 更适合访问远程文件。不幸的是,OpenSSH sftp 命令行实用程序不太适合自动化。如果您知道 python、perl 等,那么您应该考虑使用其中一种语言实现它,使用 SFTP 库。

标签: linux bash unix ssh


【解决方案1】:

与其创建 2,000 个单独的 SSH 连接,不如将整个循环推送到远程端:

# shell function which reads a NUL-delimited list of filenames on stdin
# and returns the number of them that actually exist on stdout, or "NODIR"
checkFunc() {
  test -d "$dir3" || { echo "NODIR"; return; }

  local filename successCount=0
  while IFS= read -r -d '' filename; do
    test -e "$dir3/process_${filename}.log" && (( ++successCount ))
  done
  printf '%s\n' "$successCount"
}

actual=$(
  printf '%s\0' "${FILES[@]}" | \
    ssh "$machine" "$(declare -p dir3; declare -f checkFunc); checkFunc"
) || { echo "ERROR: Unable to retrieve remote file count" >&2; exit 1; }

case $actual in
  (${#FILES[@]}) echo "SUCCESS: Expected, and found, $numberOfActuallyRemoteFiles files" ;;
  (NODIR)        echo "FAILURE: Directory $dir3 does not exist" ;;
  (*)            echo "FAILURE: Out of ${#FILES[@]} files, only $actual exist" ;;
esac

请注意,declare -p dir3declare -f checkFunc 发出的字符串在 bash 执行时将分别定义 dir3 变量或 checkFunc 函数。

【讨论】:

  • 在你的例子中 $host 来自哪里?
  • @john,这是您提供的责任。如果使用原始变量命名约定,我想它会是$machine。你仍然需要一个循环,每台机器有一个 SSH 调用——毕竟,我们需要依次连接到每一个——但关键是我们不应该调用 ssh 每台机器每个文件一次.
  • 知道了.. 所以我用完整的脚本以及迭代所有机器的循环更新了我的问题。在我们每台机器进行一个 ssh 调用的方式上,这看起来是正确的还是有什么问题?
  • 所以我运行了这个脚本,但它总是打印 "FAILURE: Out of 2000 files, only 0 exist" 并且我检查了该文件夹中远程存在的文件。有什么想法可能是错的吗?用我正在使用的完整脚本更新了我的问题。我相信问题出在checkFunc 方法或我们调用checkFunc 的方式上,但还没有弄清楚。
  • set -x;放在远程命令的开头,所以,把它改成ssh "$machine" "set -x; $(declare -p dir3; declare -f checkFunc); checkFunc"——这样我们就会得到一个执行日志,这样你就可以看到单独的test执行运行.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多