我正在编写一个 shell 脚本,该脚本应该监视一些日志文件并将输出重定向到文件。我正在使用 tail -f
命令来执行此操作,但它似乎不起作用。这是我的脚本。
#!/bin/bash
ssh -q sc-2 tail -f /home/logs/oam-2.log > /root/logs/file.log &
echo "press return to strop the trace"
read A
kill `ps -ef| grep tail| grep sc-2| grep "\.log"| awk '{print $2}'` 2>/dev/null &
当我运行脚本时,file.log 中仅打印 5 行
最佳答案
尽管您通过 &
将 ssh
进程发送到后台,但其文件描述符仍然“附加”到您的终端。演示:
# Terminal 1
$ ssh $host sleep 600 &
[3] 14340
# Terminal 2
$ ls -l /proc/14340/fd
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:30 0 -> /dev/pts/1
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:30 1 -> /dev/pts/1
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:30 2 -> /dev/pts/1
lr-x------ 1 iscfrc iscfrc 64 Oct 3 10:30 3 -> socket:[125941180]
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:31 4 -> /dev/pts/1
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:31 5 -> /dev/pts/1
lrwx------ 1 iscfrc iscfrc 64 Oct 3 10:31 6 -> /dev/pts/1
注意所有 FD(减去 TCP 套接字)如何附加到 /dev/pts/1
。
那么,当您的脚本运行 ssh
并将其置于后台,但 ssh
进程继续轮询终端以获取输入时,会发生什么情况?
# Terminal 2
$ sudo strace -p 14340
Process 14340 attached - interrupt to quit
select(7, [3 4], [], NULL, NULL
# Terminal 1
$ read
# Terminal 2, output
select(7, [3 4], [], NULL, NULL) = 1 (in [4])
read(4, 0xbff1dbbc, 16384) = ? ERESTARTSYS (To be restarted)
--- SIGTTIN (Stopped (tty input)) @ 0 (0) ---
--- SIGTTIN (Stopped (tty input)) @ 0 (0) ---
# (infinite loop of the previous three lines)
当尝试从文件描述符4
读取read()
输入时,它会陷入 panic ,您可以在上面看到它是终端。 (4 ->/dev/pts/1
)
解决方案是断开 ssh
与终端输入的连接;我建议使用 nohup
:
nohup ssh -q sc-2 tail -f /home/logs/oam-2.log > /root/logs/file.log &
供考虑的其他建议:
- 将
-T
参数添加到ssh
命令中以禁用远程主机上的 TTY 分配。由于您不需要与tail
命令交互,因此不需要 TTY。 - 通过
$!
将ssh
命令的 PID 存储到变量中,以免需要解析ps
的输出. - 为了更加简洁,您可以使用
read
的-p
选项为自己节省一个echo
。 (p
代表提示)
结合以上所有内容:
nohup ssh -qT sc-2 tail -f /home/logs/oam-2.log >/root/logs/file.log &
sshpid=$!
read -p $'press return to stop the trace\n'
kill $sshpid
我测试了上面的内容(填写了我自己的主机/文件路径),它运行了超过 10 分钟而不停止。
关于bash - 如何在 shell 脚本中使用 tail -f ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19163539/