mkdir 从命令行工作,但在使用 NFS 时C++失败

mkdir works from command line but fails in C++ when using NFS

本文关键字:NFS C++ 失败 命令行 工作 mkdir      更新时间:2023-10-16

我有一组服务器,我们使用 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");
}

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

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

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

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