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

如何让Bash函数的printf输出保留在标准输出,同时将执行命令的输出重定向到文件

如何让Bash函数的printf输出保留在标准输出,同时将执行命令的输出重定向到文件

这个问题的核心是:你调用函数时的重定向会作用于整个函数的所有输出,包括函数内部的printf和你要执行的命令(比如ssh ls),所以所有内容都进了日志文件。我们可以通过两种思路来解决这个问题:

方法一:强制printf输出到终端

直接让函数里的printf绕过外部重定向,输出到终端设备(/dev/tty),这样不管外部怎么重定向,这些提示信息都会显示在屏幕上,而命令的输出依然遵循外部的重定向规则。

修改后的函数如下:

execute_command_with_progress_bar()
{
    printf "START\n" > /dev/tty
    "$@" &

    local pid="$!"

    printf "LOOP\n" > /dev/tty

    # Signal 0 just tests whether the process exists
    while kill -0 "$pid" 2> /dev/null
    do
        printf "o" > /dev/tty
        sleep 1
    done

    printf "END\n" > /dev/tty
}

调用方式和你原来的一样就行:

execute_command_with_progress_bar ssh root@"$DEV_IP_ADDR" ls >> ./results.log 2>&1

这种方法的优点是不需要修改调用逻辑,只改函数即可;缺点是如果之后你想把printf的输出也重定向到其他地方(比如不是终端),这种方式就不适用了。

方法二:在函数内部处理命令的重定向

更灵活的方式是调整函数逻辑,让它接受日志文件作为参数,然后在函数内部把执行命令的输出重定向到该文件,而函数的printf自然输出到标准输出。

修改后的函数:

execute_command_with_progress_bar()
{
    # 第一个参数是日志文件路径
    local log_file="$1"
    # 移除第一个参数,剩下的就是要执行的命令
    shift

    printf "START\n"
    # 将命令的输出和错误都重定向到日志文件
    "$@" >> "$log_file" 2>&1 &

    local pid="$!"

    printf "LOOP\n"

    while kill -0 "$pid" 2> /dev/null
    do
        printf "o"
        sleep 1
    done

    printf "END\n"
}

调用时需要把日志文件路径放在最前面:

execute_command_with_progress_bar ./results.log ssh root@"$DEV_IP_ADDR" ls

这种方法的优势是更灵活:printf的输出可以正常被重定向(比如你想把提示信息也写到另一个文件时),日志文件的指定也更清晰。

为什么原来的写法会把所有内容都放进日志?

当你在函数调用末尾加上>> ./results.log 2>&1时,Bash会把整个函数的**所有标准输出(stdout)和标准错误(stderr)**都重定向到日志文件,不管是函数内部的printf,还是你执行的ssh ls命令的输出,都会被统一处理,所以才会出现所有内容都进文件的情况。

备注:内容来源于stack exchange,提问作者BЈовић

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 18:03:06