簡體   English   中英

從bash腳本中啟動和停止將終端輸出記錄到文件

[英]Start and stop logging terminal output to file from within bash script

基於以下三個問題:

...我整理了下面包含的腳本testlogredir.sh 它試圖做的是:運行三個命令,它們的stdout和stderr輸出將被記錄到終端和日志文件中; 然后再運行兩個命令,它們的stdout和stderr輸出僅發送到終端。 實際上,它在保留終端輸出的同時,開始和停止將腳本的終端輸出重定向到日志文件。

有趣的是,如果我在停止日志到文件后使用sleep ,那么一切都會按預期進行:

$ bash testlogredir.sh 1 y
 --- testlogredir.sh METHOD=1 DOSLEEP=y ---
aaa
bbb
ccc
ddd
eee

$ cat test.log 
aaa
bbb
ccc

...並且通過運行bash testlogredir.sh 2 y也可以獲得相同的結果。

有趣的是,如果我不使用sleep( bash testlogredir.sh 1也將獲得相同的輸出):

$ bash testlogredir.sh 2
 --- testlogredir.sh METHOD=2 DOSLEEP= ---
ddd
eee
$ aaa
bbb
ccc
^C

$ cat test.log 
aaa
bbb
ccc

...值得注意的是, 最后一個ddd ”和“ eee ”首先輸出到終端; 然后出現提示,然后輸出第一個“ aaa ”,“ bbb ”,“ ccc ”-整個過程鎖定。 所以我必須按Ctrl-C(^ C)退出它。 但是,日志文件確實具有預期的內容。

我推測,在沒有睡眠的情況下,在bash解釋器通過腳本跑這么快,它成功地呼應了“最后”二“ ddd ”和“ eee 第一 ” -然后才做tee輸出它已經存儲了(注這不是由於tee緩沖行為所致,因為我也嘗試過使用stdbuf獲得相同的結果),而且顯然是由tee進行阻塞。 因此,添加sleep可以使bash腳本與tee (sub?)進程“同步”。

顯然,我希望命令輸出按順序顯示- sleep本身並不會給我帶來太大的麻煩,因為我可以將其設置為sleep 0.1 ,幾乎不會注意到它。 但是我不得不問-這是從bash腳本中進行這種開始/停止“ tee ”重定向的正確方法嗎? 換句話說-是否可以使用sleep來實現這種“同步”呢?


testlogredir.sh

#!/usr/bin/env bash

# testlogredir.sh

# defaults:
METHOD="1"  # or "2"
DOSLEEP=""  # or "y"

if [ "$1" ] ; then
  METHOD="$1" ;
fi
if [ "$2" ] ; then
  DOSLEEP="$2" ;
fi

# this should be echoed only to terminal
echo " --- $0 METHOD=$METHOD DOSLEEP=$DOSLEEP ---"
# silent remove of test.log
rm -f test.log

if [ $METHOD == "1" ] ; then
  # Redirect 3 into (use fd3 as reference to) /dev/stdout
  exec 3> /dev/stdout
  # Redirect 4 into (use fd4 as reference to) /dev/stderr
  exec 4> /dev/stderr
fi

if [ $METHOD == "2" ] ; then
  # backup the original filedescriptors, first
  # stdout (1) into fd6; stderr (2) into fd7
  exec 6<&1
  exec 7<&2
fi

# Redirect stdout ( > ) into a named pipe ( >() ) running "tee"
#~ exec > >(stdbuf -i0 -o0 tee test.log)
exec > >(tee test.log)
# Redirect stderr (2) into stdout (1)
exec 2>&1

# these should be echoed both to terminal and log
echo "aaa"
echo "bbb"
echo "ccc" >&2

if [ $METHOD == "1" ] ; then
  # close current stdout, stderr
  exec 1>&-
  exec 2>&-
  # Redirect stdout (1) and stderr (2)
  exec 1>&3
  exec 2>&1
fi

if [ $METHOD == "2" ] ; then
  # close and restore backup; both stdout and stderr
  exec 1<&6 6<&-
  exec 2<&7 2<&-
  # Redirect stderr (2) into stdout (1)
  exec 2>&1
fi

if [ "$DOSLEEP" ] ; then
  sleep 1 ;
fi

# these should be echoed only to terminal

echo "ddd"
echo "eee" >&2

exit

您可以使用花括號來重定向命令以通過管道進行tee

#!/bin/bash

# to terminal and logfile.log
{
 echo "aaa"
 echo "bbb"
 echo "ccc"
} 2>&1 | tee logfile.log

# only terminal
echo "ddd"
echo "eee"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM