我遇到一个问题,当从远程调用 bash 脚本中的 tail 命令时,如果仅提供 2 个参数中的 1 个参数,则无法正常工作。但如果满足以下条件,它可以正常工作:
- 直接在本地执行,带 1 个参数
- 直接在本地执行,带有 2 个参数
- 使用 2 个参数从远程执行
我编写了以下脚本,以 follow 开头 tail。它需要 2 个参数:
- TESTNAME:此参数是必需的。这是测试用例的名称。它会以此名称创建一个日志文件。
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。如果我的理解有误,请告诉我,如果有更好的解决方案。