Bash函数:将命令的输出重定向到文件,但仍将函数中的printf输出打印到标准输出
我有这么一个函数:
execute_command_with_progress_bar()
{
printf "START\n"
"$@" &
local pid="$!"
printf "LOOP\n"
# Signal 0 just tests whether the process exists
while kill -0 "$pid" 2> /dev/null
do
printf "o"
sleep 1
done
printf "END\n"
}
如果我这样调用它:
execute_command_with_progress_bar ssh root@"$DEV_IP_ADDR" ls >> ./results.log 2>&1"
那么所有输出都会进入 results.log(远程 ls 的内容),以及 execute_command_with_progress_bar 函数中的所有printf调用。
我需要怎么修改,才能让远程ls的输出进入文件,而函数中的printf输出打印到标准输出?
解决方案
重新审视你的问题,看来你只需要把终端输出放到STDERR:
execute_command_with_progress_bar() {
printf "START\n" >&2
"$@" &
local pid="$!"
printf "LOOP\n" >&2
while kill -0 "$pid" 2> /dev/null; do
printf "o" >&2
sleep 1
done
printf "END\n" >&2
}
如果你想把输出既存储起来又打印到终端,你需要对它们进行多路输出。
让一个函数同时允许对STDERR与 STDOUT的重定向
并且仍然在终端输出,如 你对这个注释的请求
为此,你需要打开 另一个 文件描述符,指向 STDOUT,
请看这个
# bash source file for defining "execute_command_with_progress_bar" function
[[ $__execProgressFD ]] && [[ -t $__execProgressFD ]] ||
exec {__execProgressFD}>&1
execute_command_with_progress_bar() {
printf "START\n" >&$__execProgressFD
"$@" &
local pid="$!"
printf "LOOP\n" >&$__execProgressFD
while kill -0 "$pid" 2> /dev/null; do
printf "o" >&$__execProgressFD
sleep 1
done
wait $pid
printf "END\n" >&$__execProgressFD
}
然后:
$ . exec_progress.sh
$ execute_command_with_progress_bar >/tmp/testfile.log 2>&1 \
sh -c "sleep 2;ls -ld /tmp /tnt;sleep 2"
START
LOOP
ooooEND
$ cat /tmp/testfile.log
[1] 2228115
ls: cannot access '/tnt': No such file or directory
drwxrwxrwt 41 root root 868352 Mar 9 12:17 /tmp
[1]+ Done "$@"
或者这个,用于一个真实的旋转指示器...
# bash source file for defining "execute_command_with_spinner" function
[[ $__execProgressFD ]] && [[ -t $__execProgressFD ]] ||
exec {__execProgressFD}>&1
__execProgressSpinnerShapes=( ⢎\ ⠎⠁ ⠊⠑ ⠈⠱ \ ⡱ ⢀⡰ ⢄⡠ ⢆⡀ )
execute_command_with_spinner() {
printf "START\n" >&$__execProgressFD
"$@" &
local pid="$!" pnt
printf "LOOP\e[?25l\n" >&$__execProgressFD # cursor invisible
while kill -0 "$pid" 2> /dev/null; do
# Save cursor position, render frame, restore cursor position
printf >&$__execProgressFD '\e7%b\e8' \
"${__execProgressSpinnerShapes[pnt++ %
${#__execProgressSpinnerShapes[@]}]}"
read -rsn 1 -t .05 _
done
wait $pid
printf "\e[?25h\rEND\n" >&$__execProgressFD # cursor visible
}
注意:如果在GNU/Linux下运行,最好使用 /proc 伪文件系统,而不是为每次循环都fork到 kill。将 kill -0 替换为:
while [[ -d /proc/$pid ]]; do
但如果你想在打印时同时存储输出
为此,你可以使用 tee 命令:
logfile="path/to/logfile.log"
exec 1> >(tee /dev/tty >>"$logfile")
然后发往 STDOUT 的所有内容都会被追加到 $logfile,并同时发送到当前终端。
更多示例和信息在
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。