bash - 如何在 shell 脚本中使用 tail -f ?

标签 bash shell

我正在编写一个 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 &

供考虑的其他建议:

  1. -T 参数添加到 ssh 命令中以禁用远程主机上的 TTY 分配。由于您不需要与 tail 命令交互,因此不需要 TTY。
  2. 通过 $!ssh 命令的 PID 存储到变量中,以免需要解析 ps 的输出.
  3. 为了更加简洁,您可以使用 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/

相关文章:

linux - 如何在shell脚本中的if else语句中将输出写入文件

java - 如何在 Java 中为 OS X 运行 sudo 命令

java - 在 Eclipse 中的 Java 代码运行时执行 shell 脚本

linux - 如何在linux中捕获用户执行的命令

shell - 获取第 n 个工作日的 unix shell 脚本

c - shell执行自定义函数不起作用

bash - 为什么我们可以通过添加 "g"来用 sed 替换字符串?

bash - 获取实际提示长度

macos - Bash 命令替换 stdout+stderr 重定向

bash - 使用 bash 查找包含字符串的第一个文件夹名称