C# 具有.NET内核的Linux/Unix上的文件权限
我正在尝试学习如何使用.NET内核在Linux/Unix上设置文件权限。我已经在这里找到了一个问题,它为我指明了System.IO.FileSystem的方向,但是我似乎找不到任何关于如何使用它的文档C# 具有.NET内核的Linux/Unix上的文件权限,c#,.net,asp.net-core,.net-core,C#,.net,Asp.net Core,.net Core,我正在尝试学习如何使用.NET内核在Linux/Unix上设置文件权限。我已经在这里找到了一个问题,它为我指明了System.IO.FileSystem的方向,但是我似乎找不到任何关于如何使用它的文档 简而言之,我想从一个只在Linux上运行的.NET Core应用程序中chmod一个文件644,但我不知道如何继续。目前,.NET Core中没有用于此的内置API。然而,.NET核心团队正在努力使Mono.Posix在.NET核心上可用。这将公开API以在托管代码中执行此类操作。见和。您可以在此
简而言之,我想从一个只在Linux上运行的.NET Core应用程序中chmod一个文件644,但我不知道如何继续。目前,.NET Core中没有用于此的内置API。然而,.NET核心团队正在努力使
Mono.Posix
在.NET核心上可用。这将公开API以在托管代码中执行此类操作。见和。您可以在此处尝试此API的早期版本:
如果不想使用Mono.Posix,可以通过调用本机代码来实现相同的功能。使用P/Invoke,您可以从libc
调用chmod
函数。有关本机API的更多详细信息,请参见man 2 chmod
using System;
using System.IO;
using System.Runtime.InteropServices;
using static System.Console;
class Program
{
[DllImport("libc", SetLastError = true)]
private static extern int chmod(string pathname, int mode);
// user permissions
const int S_IRUSR = 0x100;
const int S_IWUSR = 0x80;
const int S_IXUSR = 0x40;
// group permission
const int S_IRGRP = 0x20;
const int S_IWGRP = 0x10;
const int S_IXGRP = 0x8;
// other permissions
const int S_IROTH = 0x4;
const int S_IWOTH = 0x2;
const int S_IXOTH = 0x1;
static void Main(string[] args)
{
WriteLine("Setting permissions to 0755 on test.sh");
const int _0755 =
S_IRUSR | S_IXUSR | S_IWUSR
| S_IRGRP | S_IXGRP
| S_IROTH | S_IXOTH;
WriteLine("Result = " + chmod(Path.GetFullPath("test.sh"), (int)_0755));
WriteLine("Setting permissions to 0644 on sample.txt");
const int _0644 =
S_IRUSR | S_IWUSR
| S_IRGRP
| S_IROTH;
WriteLine("Result = " + chmod(Path.GetFullPath("sample.txt"), _0644));
WriteLine("Setting permissions to 0600 on secret.txt");
const int _0600 = S_IRUSR | S_IWUSR;
WriteLine("Result = " + chmod(Path.GetFullPath("secret.txt"), _0600));
}
}
我通过启动一个新进程并执行bash
chmod
命令解决了这个问题
示例:
public static void Exec(string cmd)
{
var escapedArgs = cmd.Replace("\"", "\\\"");
using var process = new Process
{
StartInfo = new ProcessStartInfo
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "/bin/bash",
Arguments = $"-c \"{escapedArgs}\""
}
};
process.Start();
process.WaitForExit();
}
然后:
Exec("chmod 644 /path/to/file.txt");
您还可以使用此
Exec
方法来运行任何其他类型的bash命令。与@kspearrin建议的方法类似,但为了简单起见,请使用:
public静态异步值任务SetPermissionsAsync(字符串文件路径,字符串权限)=>
等待Cli.Wrap(“/bin/bash”)
.WithArguments(新[]{“-c”,$“chmod{permissions}{filePath}})
.ExecuteAsync();
自动处理转义、错误等。这里有一个简单的chmod函数,可以在c#中使用,没有依赖性
// Returns true if success and false otherwise
// permissions can be an int or a string. For example it can also be +x, -x etc..
bool Chmod(string filePath, string permissions = "700", bool recursive = false)
{
string cmd;
if (recursive)
cmd = $"chmod -R {permissions} {filePath}";
else
cmd = $"chmod {permissions} {filePath}";
try
{
using (Process proc = Process.Start("/bin/bash", $"-c \"{cmd}\""))
{
proc.WaitForExit();
return proc.ExitCode == 0;
}
}
catch
{
return false;
}
}
Microsoft在Windows上使用他们的文件权限模型,并将其转换为Linux/UNIX。因此,对
chmod
的调用是内部调用,并且仅用于So。在您的情况下,您必须将644转换为相应的Windows文件权限,然后使用Windows方式操作该文件。注意-NuGet软件包已过测试版:我发现我必须发布unixFileInfo.Refresh()
立即将更改提交到文件系统。否则,这些更改将在稍后的某个未指定时间显示。好奇是否有人看到过这一点?您是否使用.NetCore运行本机代码示例?最初的帖子是几年前发布的,所以请登录查看“bash/chmod”和Mono.Postix包是否还有其他替代方案。
// Returns true if success and false otherwise
// permissions can be an int or a string. For example it can also be +x, -x etc..
bool Chmod(string filePath, string permissions = "700", bool recursive = false)
{
string cmd;
if (recursive)
cmd = $"chmod -R {permissions} {filePath}";
else
cmd = $"chmod {permissions} {filePath}";
try
{
using (Process proc = Process.Start("/bin/bash", $"-c \"{cmd}\""))
{
proc.WaitForExit();
return proc.ExitCode == 0;
}
}
catch
{
return false;
}
}