使用 ssh.net 在 ubuntu 服务器上的文件末尾写入

Write in the end of a file on ubuntu server using ssh.net

我想使用ssh.net向\etc\ssh\sshd_config添加一些行,我试过这个方法 SFTPCLient.WriteAllLines(string path, string[] content) 但它在删除相同行数后在文件开头添加 content 。在文档中我发现这个 It is not first truncated to zero bytes. 是什么意思? 我也用另一个文件尝试过这种方法public abstract void Write(byte[] buffer, int offset, int count); ,因为我不想冒险删除其他行,但它不起作用,谁能解释偏移量和计数必须采用的值?

string[] config = {"Match user Fadwa", "ChrootDirectory /fadwa/dhifi/test",
    "ForceCommand internal-sftp -d /fadwa"};

byte[] bconfig = config.SelectMany(s =>Encoding.UTF8.GetBytes(s + 
    Environment.NewLine)).ToArray();
Renci.SshNet.Sftp.SftpFileStream stream = sftpClient.OpenWrite("/sftp/dhifi/test.txt");
if (stream.CanWrite)
{
    stream.Write(bconfig,0,bconfig.Length);
}
else Console.WriteLine("Can't Write right now ! "); 

否则,欢迎任何其他解决方案,在此先感谢!

SftpClient.OpenWrite() creates a Stream 定位在文件开头。 “它不是首先被截断为零字节”意味着 Stream 不会 写入实际上是空文件的内容,而是覆盖文件的现有字节。因此,如果现有文件比 SftpFileStream.Write()content 参数长,生成的文件将由 content 后跟现有文件的其余部分组成,这正是您观察到的。

查看 the documentation 我看到了一些解决方案:

  • SftpClient.AppendAllLines():

    sftpClient.AppendAllLines("/sftp/dhifi/test.txt", config);
    
  • SftpClient.AppendText():

    using (StreamWriter writer = sftpClient.AppendText("/sftp/dhifi/test.txt"))
        foreach (string line in config)
            writer.WriteLine(line);
    
  • 因为你想在文件末尾开始写入,而不是 SftpClient.OpenWrite() 你可以调用 SftpClient.Open(),它允许你指定一个 FileModeAppend

    using (SftpFileStream stream = sftpClient.Open("/sftp/dhifi/test.txt", FileMode.Open | FileMode.Append))
        stream.Write(bconfig, 0, bconfig.Length);
    

    我认为您对 CanWrite 的检查没有必要,因为如果 FileAccess.Write 无法被授予,Stream 应该首先无法打开。

    如果 FileMode.Append 由于某种原因不能与 SSH.NET 一起使用(看起来它可以,因为那是 what AppendText() uses) you could instead use 并在写入文件之前查找到文件末尾:

    using (SftpFileStream stream = sftpClient.OpenWrite("/sftp/dhifi/test.txt"))
    {
        stream.Seek(0, SeekOrigin.End);
        stream.Write(bconfig, 0, bconfig.Length);
    }
    

顺便说一句,另一种在 config 行之间注入 NewLines 的方法是...

byte[] bconfig = Encoding.UTF8.GetBytes(
    string.Join(Environment.NewLine, config)
);

因为它减少了中间 strings 和 byte[]s 的数量,所以它更短且更有效。