AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 414892
Accepted
PhilBot
PhilBot
Asked: 2018-01-05 16:31:27 +0800 CST2018-01-05 16:31:27 +0800 CST 2018-01-05 16:31:27 +0800 CST

如何终止 Linux tee 命令而不杀死它正在接收的应用程序

  • 772

我有一个 bash 脚本,只要 Linux 机器开机就可以运行。我启动它如下所示:

( /mnt/apps/start.sh 2>&1 | tee /tmp/nginx/debug_log.log ) &

启动后,我可以在ps输出中看到 tee 命令,如下所示:

$ ps | grep tee
  418 root       0:02 tee /tmp/nginx/debug_log.log
3557 root       0:00 grep tee

我有一个函数可以监视tee生成的日志的大小,并在日志达到一定大小时终止tee命令:

monitor_debug_log_size() {
                ## Monitor the file size of the debug log to make sure it does not get too big
                while true; do
                                cecho r "CHECKING DEBUG LOG SIZE... "
                                debugLogSizeBytes=$(stat -c%s "/tmp/nginx/debug_log.log")
                                cecho r "DEBUG LOG SIZE: $debugLogSizeBytes"
                                if [ $((debugLogSizeBytes)) -gt 100000 ]; then
                                                cecho r "DEBUG LOG HAS GROWN TO LARGE... "
                                                sleep 3
                                                #rm -rf /tmp/nginx/debug_log.log 1>/dev/null 2>/dev/null
                                                kill -9 `pgrep -f tee`
                                fi
                                sleep 30
                done
}

令我惊讶的是,杀死tee命令也会被 start.sh 实例杀死。为什么是这样?如何结束tee命令但让我的 start.sh 继续运行?谢谢。

linux scripting
  • 2 2 个回答
  • 6192 Views

2 个回答

  • Voted
  1. Best Answer
    Wildcard
    2018-01-05T17:04:25+08:002018-01-05T17:04:25+08:00

    终止时tee,提供它的命令将继续运行,直到它尝试写入更多输出。然后它将获得一个 SIGPIPE(在大多数系统上为 13),用于尝试写入没有读取器的管道。

    如果您修改脚本以捕获 SIGPIPE 并采取一些适当的操作(例如,停止写入输出),那么您应该能够在 tee 终止后继续它。


    更好的是,为了简单起见tee ,使用选项而不是杀死。logrotatecopytruncate

    引用logrotate(8):

    copytruncate

    创建副本后在原地截断原始日志文件,而不是移动旧日志文件并选择性地创建新日志文件。当某些程序无法被告知关闭其日志文件并因此可能永远继续写入(附加)到前一个日志文件时,可以使用它。请注意,复制文件和截断文件之间的时间片非常短,因此可能会丢失一些日志记录数据。使用此选项时,create 选项将不起作用,因为旧日志文件保留在原处。

    • 36
  2. Charles Duffy
    2018-01-06T14:07:35+08:002018-01-06T14:07:35+08:00

    解释“为什么”

    简而言之:如果写入失败没有导致程序退出(默认情况下),我们就会一团糟。考虑一下find . | head -n 10——您不想find继续运行,扫描硬盘驱动器的其余部分,在head已经占用了它需要的 10 行并继续之前。

    做得更好:在您的记录器内旋转

    考虑以下根本不使用tee的示例:

    #!/usr/bin/env bash
    
    file=${1:-debug.log}                     # filename as 1st argument
    max_size=${2:-100000}                    # max size as 2nd argument
    size=$(stat --format=%s -- "$file") || exit  # Use GNU stat to retrieve size
    exec >>"$file"                           # Open file for append
    
    while IFS= read -r line; do              # read a line from stdin
      size=$(( size + ${#line} + 1 ))        # add line's length + 1 to our counter
      if (( size > max_size )); then         # and if it exceeds our maximum...
        mv -- "$file" "$file.old"            # ...rename the file away...
        exec >"$file"                        # ...and reopen a new file as stdout
        size=0                               # ...resetting our size counter
      fi
      printf '%s\n' "$line"                  # regardless, append to our current stdout
    done
    

    如果运行为:

    /mnt/apps/start.sh 2>&1 | above-script /tmp/nginx/debug_log
    

    ...这将首先附加到/tmp/nginx/debug_log,将文件重命名/tmp/nginx/debug_log.old为存在超过 100KB 的内容。因为记录器本身在进行旋转,所以当旋转发生时没有损坏的管道,没有错误,也没有数据丢失窗口——每一行都将被写入一个或另一个文件。

    当然,在本机 bash 中实现这一点效率很低,但以上只是一个说明性示例。有许多程序可以为您实现上述逻辑。考虑:

    • svlogd,来自 Runit 套件的服务记录器。
    • s6-log,一个积极维护的替代 skanet 套件。
    • multilog来自 DJB Daemontools,该系列流程监督和监控工具的鼻祖。
    • 3

相关问题

  • 使用键盘快捷键启动/停止 systemd 服务 [关闭]

  • 需要一些系统调用

  • 根据其中的值批量重命名(附加)CSV 文件

  • astyle 不会更改源文件格式

  • 通过标签将根文件系统传递给linux内核

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve