通过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
相关产品推荐
相关产品推荐

