【问题标题】:mkdir works from command line but fails in C++ when using NFSmkdir 从命令行工作,但在使用 NFS 时在 C++ 中失败
【发布时间】:2017-07-11 11:27:06
【问题描述】:

我有一组服务器,我们正在使用 NFS 将每个服务器的驱动器安装到所有其他服务器上。我们能够毫无问题地安装驱动器。我可以从命令行调用 mkdir 到已安装 nfs 的驱动器之一,一切正常。但是,如果我尝试从用 C 编写的程序运行 mkdir。它说当我们尝试运行 mkdir 时文件或目录不存在。它不是试图创建多级目录或类似的东西。它以完全相同的权限在完全相同的位置尝试,但由于某种原因,当我们从 C 调用 mkdir 时,它会给出文件不存在的消息(我假设它表示父目录)。

#include <sys/stat.h>

#include <vector>
#include <dirent.h>
#include <string>
#include <mutex>
#include <iosfwd>
#include <iostream>
#include <fstream>
#include <thread>
#include <string.h>
#include <chrono>
#include <cerrno>

#include <dirent.h>
#include <fcntl.h>  // O_RDONLY
#include <unistd.h> // read
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>



    #define FILE_PERMISSION_BITS_MODE 0700
    int makeDir(std::string folderPath){

        bool dirExists = false;
        int success = -1;
        struct stat sb;
        if (stat(folderPath.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)){
            dirExists = true;
            success = 0;
        }

        if (!dirExists){
            int success = mkdir(folderPath.c_str(),FILE_PERMISSION_BITS_MODE);

            int countInvalids = 0;

            while (success != 0 ){

                if (success == -1 && stat(folderPath.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)){ // if failed, check again if it exists or not
                    success = 0;
                    break;
                }

                int fileRetryDelay = 20;
                const int sleep_milliseconds = (countInvalids+1)*fileRetryDelay;
                std::this_thread::sleep_for(std::chrono::milliseconds(sleep_milliseconds));

                if (countInvalids % 5 == 0){
                    const std::string sysError(std::strerror(errno));

                    std::cout<<"ERROR: FileUtil::makeDir failed to make directory: " << folderPath<<" try number "<<countInvalids << "   Error was: "<< sysError << " (" << errno << ")"<<std::endl;
                }
                countInvalids++;

                success = mkdir(folderPath.c_str(),FILE_PERMISSION_BITS_MODE);

                if (countInvalids > 10000){
                    break;
                }
            }
            if (success == 0 && countInvalids > 0){
                std::cout<<"FileUtil::makeDir finally succeeded making directory: " << folderPath << "   Succeeded after "<<countInvalids<<" tries"<<std::endl;
            }
        }

        if (success == -1 && stat(folderPath.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)){ // if failed, check again if it exists or not
            success = 0;
        }

        return success;

    }


int main(){
     makeDir("/some/path");
}

【问题讨论】:

  • 您能否尝试为失败的程序创建一个Minimal, Complete, and Verifiable Example 并向我们展示?
  • 如果没有所谓的创建目录的代码行,我们如何回答这个问题?
  • 命令行“mkdir”是用C编写的。你自己的实现可能是错误的,或者你比较了2个不同上下文中的2个执行。
  • 我刚刚添加了创建目录的代码。确实很简单,失败的行是 success = mkdir(folderPath.c_str(),FILE_PERMISSION_BITS_MODE);因为有时 NFS 会失败,但实际上最终会创建目录,我们还会在每次创建尝试后检查它是否存在。
  • 您的代码中存在一个问题:您没有在应该检查或保存errno 的值时检查或保存。您需要在失败的函数之后立即检查(或保存)errno 的值。否则,errno 的值可能在 POSIX 系统上变得未定义。

标签: c++ mkdir nfs


【解决方案1】:

所以经过一番挖掘,我们弄清楚了发生了什么。

  1. 如前所述,我们需要在调用后立即捕获 errno,因为几毫秒后捕获的 errno 并不相同。

  2. 使用 NFS 并以 root 身份运行应用程序时,您需要使用选项 no_root_squash 才能写入您正在访问的文件系统。

我们没有使用 no_root_squash 选项(由于显而易见的原因不安全),我们确保我们的应用程序不是在 sudo 下运行或由 root 用户运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-28
    相关资源
    最近更新 更多