You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何创建归属指定用户组(而非默认组)的目录?

问题描述

我正在编写一个程序,计划以守护进程/服务/无登录用户aaa运行。用户aaa属于shareabc和sharedef组。程序的配置文件如下:

{
   ... other config ...
   "locations": [
      {
         "id": "workflow1",
         "location": "/shr/abc",
         "group": "shareabc"
      },
      {
         "id": "workflow2",
         "location": "/shr/def",
         "group": "sharedef"
      },
   ],
   ... other config ...
}

相关目录归属情况:

  • /shr/abc 归属为 root:shareabc
  • /shr/def 归属为 root:sharedef

调用Directory.CreateDirectory("/shr/abc/myfolder1");创建的/shr/abc/myfolder1会归属aaa:aaa,需要编写C#代码让该目录归属为aaa:shareabc。

排除方案说明:
将程序以用户aaa、组shareabc运行并非解决方案,原因如下:

  • 部分文件需归属aaa:aaa,另一部分需归属aaa:shareabc,修改运行用户/组或文件系统默认设置仅会转移问题,而非解决问题。
  • 当程序尝试写入/shr/def目录并需使其归属aaa:sharedef时,会遇到相同问题。

补充信息:
关于权限设置,C# API已在数年前更新,可通过以下代码创建权限为775的目录:

Directory.CreateDirectory("/shr/abc/myfolder1", UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute | UnixFileMode.OtherRead | UnixFileMode.OtherExecute);
解决方案

要让创建的目录归属为aaa:shareabc,需要在创建目录后手动修改其组所有权。以下是具体实现方式:

.NET 7+ 原生实现(推荐)

.NET 7及以上版本提供了UnixGroupInfo类,可以直接获取组ID,无需P/Invoke:

using System.IO;
using System.Security.Principal;

var targetDir = "/shr/abc/myfolder1";
var targetGroup = "shareabc";

// 创建目录并设置775权限
Directory.CreateDirectory(targetDir, 
    UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
    UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute |
    UnixFileMode.OtherRead | UnixFileMode.OtherExecute);

// 获取目标组的ID
var groupInfo = new UnixGroupInfo(targetGroup);
int groupId = groupInfo.GroupId;

// 修改目录的组所有者
var dirInfo = new DirectoryInfo(targetDir);
dirInfo.UnixFileInfo.GroupOwnerId = groupId;

兼容旧版本.NET(.NET Core 3.1/.NET 5/.NET 6)

如果使用的是较低版本的.NET,可以通过P/Invoke调用系统libc的getgrnam函数获取组ID,再修改目录组所有权:

using System;
using System.IO;
using System.Runtime.InteropServices;

var targetDir = "/shr/abc/myfolder1";
var targetGroup = "shareabc";

// 创建目录并设置775权限
Directory.CreateDirectory(targetDir, 
    UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
    UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute |
    UnixFileMode.OtherRead | UnixFileMode.OtherExecute);

// 获取目标组ID
int groupId = GetGroupId(targetGroup);

// 修改目录的组所有者
var dirInfo = new DirectoryInfo(targetDir);
dirInfo.UnixFileInfo.GroupOwnerId = groupId;

// P/Invoke 获取组ID的实现
[DllImport("libc", SetLastError = true)]
private static extern IntPtr getgrnam(string name);

private static int GetGroupId(string groupName)
{
    IntPtr grpPtr = getgrnam(groupName);
    if (grpPtr == IntPtr.Zero)
    {
        throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
    }

    Group grp = Marshal.PtrToStructure<Group>(grpPtr);
    return grp.gr_gid;
}

[StructLayout(LayoutKind.Sequential)]
private struct Group
{
    public IntPtr gr_name;
    public IntPtr gr_passwd;
    public int gr_gid;
    public IntPtr gr_mem;
}

说明:

  • 以上代码仅在Unix-like系统(Linux、macOS等)下有效,Windows系统不支持UnixFileInfo及相关API。
  • 运行程序的用户aaa需要具备修改目标目录组所有权的权限,由于aaa属于shareabc组,且父目录/shr/abc的组是shareabc,因此权限是足够的。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 08:56:01