在特定情况下,shell 脚本中带有重定向的 nohup tail 命令无法正确调用

在特定情况下,shell 脚本中带有重定向的 nohup tail 命令无法正确调用

我遇到一个问题,当从远程调用 bash 脚本中的 tail 命令时,如果仅提供 2 个参数中的 1 个参数,则无法正常工作。但如果满足以下条件,它可以正常工作:

  • 直接在本地执行,带 1 个参数
  • 直接在本地执行,带有 2 个参数
  • 使用 2 个参数从远程执行

我编写了以下脚本,以 follow 开头 tail。它需要 2 个参数:

  1. TESTNAME:此参数是必需的。这是测试用例的名称。它会以此名称创建一个日志文件。
  2. SLAVE_HOST :此参数是可选的。如果提供,它将 ssh 到提供的从属主机并在其上启动类似的脚本。

    #!/bin/bash
    TESTNAME="$1"
    
    testdate=$(date +'%m_%d_%Y')
    REG_DIR=/opt/reg-test-results/REG_"$testdate"
    
    #create regression results directory if it does not exist
    mkdir -p "$REG_DIR"
    
    FILENAME="$REG_DIR"/"$TESTNAME"
    
    #if file already exists, create a new one with current time stamp appended to name
    if [ -f "$FILENAME" ]; then
           TIME=$(date +'%m_%d_%Y-%H.%M.%S')
           FILENAME="$FILENAME"_"$TIME"
    fi
    
    echo "$FILENAME" > /opt/reg-test-results/currentTestName
    
    #start tailing
    nohup tail -f -n0 /path/to/log/files/*/*server.log > "$FILENAME" &
    echo "$!" > $REG_DIR/reg_tail.pid
    
    #if slave host is provided, start tailing logs on slave also
    if [ "$#" -gt 1 ]; then
           SLAVE_HOST="$2"
           ssh "$SLAVE_HOST" /path/to/script/startTailLogTestCaseSlave.sh "$FILENAME"
    fi
    

前几行代码将参数保存在变量中,为日志文件创建目录结构和文件名,跟踪日志将定向到该日志文件。之后,我使用 nohup tail 命令来开始跟踪日志并定向到日志文件。这是无法正常工作的代码行。然后,如果提供了第二个参数,它将 ssh 到该主机并在其上执行命令。

问题:当从远程运行并传递两个参数时,执行此脚本后,我看到一个 tail 进程正在运行,并且我看到日志文件被正确填充了内容。但如果我只提供第一个参数,那么它似乎启动了 tail 然后立即停止它,因为我在 reg_tail.pid 文件中看到了一个新的进程 id,但日志文件 ($FILENAME) 并未创建,并且没有 tail 进程正在运行。

当直接在机器上执行时,脚本无论使用 1 个参数还是两个参数都可以完美运行。

所谓“远程运行时”,是指通过 ssh 连接到计算机并调用脚本。例如:

$ ssh -t user@host /path/to/script/script.sh testcasename.log

调试工作量:

这是我使用 set -x 并从远程机器运行时看到的内容:

当传递第二个参数并且一切正常运行时,我看到 nohup tail 在最后执行。

  ....
  + echo 13441
  + '[' 2 -gt 1 ']'
  + SLAVE_HOST=slaveHost
  + ssh slaveHost /path/to/script/startTailLogTestCaseSlave.sh /opt/reg-test-   results/REG_09_11_2015/logs2.log
  + nohup tail -f -n0 /path/to/logs/../check-server.log ...
  nohup: redirecting stderr to stdout
  Connection to hostname closed.

当仅传递第一个参数时,nohup tail 永远不会执行:

  ...
  + echo 13607
  + '[' 1 -gt 1 ']'
  Connection to hostname closed.

答案1

我通过在 tail 命令后添加延迟解决了该问题。

nohup tail -f -n0 /path/to/log/files/*/*server.log > "$FILENAME" 2> test.err < /dev/null &
echo "$!" > "$REG_DIR"/reg_tail.pid

#without this delay, the above tail command is not being executed when only one 1 argumet is passed
sleep 1

#if slave host is provided, start tailing logs on slave also
if [ "$#" -gt 1 ]; then

我想知道为什么它在执行 ssh 命令后会起作用,尽管它与此无关。所以,我决定添加一个延迟。虽然我不是专家,但它看起来像是一种竞争条件。tail 后台进程被安排在最后运行,并且在没有执行 ssh 命令的情况下,脚本退出并且会话在 tail 进程有机会运行之前结束。将主进程置于睡眠状态使 tail 进程(或线程)有机会运行。鉴于此,我不确定这个解决方案是否最好。如果我使用 wait 而不是 sleep,它会卡住,因为“tail -f”将继续运行。我正在使用此脚本来跟踪日志,然后运行测试用例。测试用例执行完成后,我正在运行另一个脚本,该脚本从存储 tail 的位置读取它的 pid 并终止 tail。如果我的理解有误,请告诉我,如果有更好的解决方案。

相关内容