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

通过ssh.Client上传文件时若目标路径不存在如何自动创建目录

解决方法

方案1:保留scp逻辑,新增目录创建步骤

不需要完全替换scp命令,只要在执行scp操作前先执行创建父目录的命令即可:

  • 提取目标路径父目录并创建的命令:sudo mkdir -p "$(dirname <目标路径>)"
    • -p参数会自动创建所有不存在的父级目录,对应目录已存在时也不会报错
    • 加sudo和后续scp的权限保持一致,避免/etc等系统目录无写入权限的问题

修改后的完整代码示例:

func upload(con *ssh.Client, buf bytes.Buffer, path string, content []byte) error {
    session, err := con.NewSession()
    if err != nil {
        return err
    }
    defer session.Close()

    // 新增:先创建目标目录层级
    mkdirCmd := "sudo mkdir -p \"$(dirname " + path + ")\""
    buf.WriteString(mkdirCmd + "\n")
    mkdirOutput, err := session.CombinedOutput(mkdirCmd)
    buf.Write(mkdirOutput)
    if err != nil {
        return &DeployError{
            Err:    err,
            Output: buf.String(),
        }
    }

    // 原有scp逻辑保持不变
    buf.WriteString("sudo scp -t " + path + "\n")
    stdin, err := session.StdinPipe()
    if err != nil {
        return err
    }
    go func() {
        defer stdin.Close()
        fmt.Fprint(stdin, "C0660 "+strconv.Itoa(len(content))+" file\n")
        stdin.Write(content)
        fmt.Fprint(stdin, "\x00")
    }()

    output, err := session.CombinedOutput("sudo scp -t " + path)
    buf.Write(output)
    if err != nil {
        return &DeployError{
            Err:    err,
            Output: buf.String(),
        }
    }

    return nil
}

方案2:替换scp为rsync,自动创建目录

如果目标机器安装了rsync,也可以直接替换scp命令,rsync自带--mkpath参数会自动创建不存在的父目录,不需要额外执行mkdir命令:

  • 替换后的命令:sudo rsync --mkpath -p 0660 /dev/stdin <目标路径>

替换后的核心代码段:

// 替换原有scp命令写入部分
buf.WriteString("sudo rsync --mkpath -p 0660 /dev/stdin " + path + "\n")
// 后续stdin写入文件内容的逻辑无需改动
output, err := session.CombinedOutput("sudo rsync --mkpath -p 0660 /dev/stdin " + path)

注意:如果你的路径可能包含空格、特殊字符,建议先对path参数做shell转义处理后再拼接命令,避免执行异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:36:03