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

C语言调用system执行SFTP命令输出未屏蔽、错误状态无法识别问题

问题原因及解决方案

问题1:重定向stdout/stderr后仍有终端输出

原因

OpenSSH的sftp工具默认运行在交互模式下,连接提示、命令提示符、传输状态等信息会直接写入当前进程关联的终端设备/dev/tty,不属于标准输出(stdout,文件描述符1)和标准错误(stderr,文件描述符2),因此对1和2的重定向无法拦截这类输出。

解决方法

修改sftp启动参数,关闭交互模式、开启静音模式:

  • 新增-q参数:启用静音模式,抑制连接提示、传输状态等非必要输出
  • 新增-b -参数:指定从标准输入读取批处理命令,完全关闭交互逻辑,不再向/dev/tty写入内容
  • 可选新增-o BatchMode=yes参数:禁用交互式密码输入,避免网络异常或认证失败时进程卡住

修改后的完整命令为:

echo "put /home/file1.txt /home/file2.txt" | sftp -q -F /dev/null -P 22022 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o BatchMode=yes -b - admin@10.113.21.89 > /dev/null 2>&1

问题2:传输失败无法识别错误返回

原因

存在两个问题共同导致:

  1. sftp交互模式下,单条命令执行失败不会触发整个sftp进程返回非0退出码,默认始终返回0
  2. 原有C代码的返回值判断逻辑完全错误:只要sftp进程正常退出(无论执行成功还是失败),就直接返回-1;反而进程异常终止时才返回0,和预期逻辑完全相反。

解决方法

  1. 按问题1的方案修改sftp参数,启用批处理模式:批处理模式下任意命令执行失败,sftp进程就会返回非0的退出码
  2. 修正C代码的返回值判断逻辑:进程正常退出时,通过WEXITSTATUS拿到的返回值为0代表传输成功,非0代表传输失败。

修改后的完整C代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

int sftpFile()
{
    char cmd[256] = "echo \"put /home/file1.txt /home/file2.txt\" | sftp -q -F /dev/null -P 22022 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o BatchMode=yes -b - admin@10.113.21.89 > /dev/null 2>&1";
    
    int status = system(cmd);
    
    // system调用本身失败(无法启动shell)
    if (status == -1) {
        perror("system call failed");
        return -1;
    }
    
    // sftp进程正常退出
    if (WIFEXITED(status)) {
        int exit_code = WEXITSTATUS(status);
        printf("sftp exit_code: %d\n", exit_code);
        // 退出码为0代表传输成功
        if (exit_code == 0) {
            return 0;
        } else {
            return -1;
        }
    }
    
    // sftp进程异常终止(被信号杀死等)
    return -1;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:24:00