bash 使用 SOCAT 记录在端口上收到的消息

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13512760/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 03:50:44  来源:igfitidea点击:

Recording messages received on a port with SOCAT

linuxbashtcpportsocat

提问by user1844937

I have a server with an open port which receives between 50 and 1000 messages per second. By message I mean that a single line of text is sent.

我有一个带有开放端口的服务器,每秒接收 50 到 1000 条消息。我所说的消息是指发送一行文本。

Essentially we want to record these messages in a file which will be processed every hour (or x minutes).

本质上,我们希望将这些消息记录在一个文件中,该文件将每小时(或 x 分钟)处理一次。

I have created a bash script (see below) which runs in the background and it works except when I kill the socat process (so I can take the file for processing and it can start a new file) we get part of a message, plus I am sure we are losing messages during the split second that socat is down.

我创建了一个在后台运行的 bash 脚本(见下文),它可以工作,除非我杀死 socat 进程(这样我就可以处理文件,它可以启动一个新文件)我们得到了一条消息的一部分,加上我确信在 socat 关闭的那一瞬间,我们正在丢失消息。

DELAY="3600"
while true
do  
    NEXT_STOP=`date +%s --date "$DELAY second"`
    (
        while [ "$(date +%s)" -lt "$NEXT_STOP" ]
        do
            killall socat
            socat -u TCP-LISTEN:6116,reuseaddr,keepalive,rcvbuf=131071,reuseaddr OPEN:/var/ais/out_v4.txt,creat,append
        done
    ) & sleep $DELAY ; killall socat

    mv /var/ais/out_v4.txt "/var/ais/_socat_received/"$(date +"%Y-%m-%d-%T")"__out_v4.txt"
done

Is there a way to:

有没有办法:

  1. Get socat to rotate its output file without killing the process
  2. Or can we purge the content of the file whilst SOCAT is writing to it. e.g. cut the first 10000 lines into another file, so the output file remains a manageable size?
  1. 让 socat 在不终止进程的情况下旋转其输出文件
  2. 或者我们可以在 SOCAT 写入文件时清除文件的内容。例如,将前 10000 行剪切到另一个文件中,以便输出文件保持可管理的大小?

Many thanks in advance

提前谢谢了

采纳答案by user1844937

For anyone interested the final solution looks like the following, the key difference to Nicholas solution below is that I needed to grep the PID of the socat process rather than use $?:

对于任何感兴趣的人,最终解决方案如下所示,与下面的 Nicholas 解决方案的主要区别在于,我需要 grep socat 进程的 PID 而不是使用 $?:

#!/bin/bash
DELAY=600
SOCAT_PID=$(/bin/ps -eo pid,args | grep "socat -u TCP-LISTEN:12456" | grep -v grep | awk '{ print  }')

while `kill -0 $SOCAT_PID`
do  
  touch /var/ais/out.txt
  NEXT_STOP=`date +%s --date "$DELAY second"`
  while  `kill -0 $SOCAT_PID` && [ "$(date +%s)" -lt "$NEXT_STOP" ]
  do
    head -q - >> /var/ais/out.txt
  done
  mv /var/ais/out.txt "/var/ais/_socat_received/"$(date +"%Y-%m-%d-%T")"__out.txt"
done

In addition adding the start script within an infinite while loop so that when the client disconnects we restart socat and wait for the next connection attempt:

此外在无限循环中添加启动脚本,以便当客户端断开连接时我们重新启动 socat 并等待下一次连接尝试:

while true
do
socat -u TCP-LISTEN:12456,keepalive,reuseaddr,rcvbuf=131071 STDOUT | /var/ais/socat_write.sh
done

回答by Aryeh Leib Taurog

Instead of reinventing the wheel, you could use rotatelogsor multilog, both of which read log messages on std input and write them to log files with very flexible rotation config.

您可以使用rotatelogsmultilog代替重新发明轮子,这两者都读取 std 输入上的日志消息并将它们写入具有非常灵活的轮换配置的日志文件。

Even one step higher, the functionality you described is very similar to what rsyslogdand the like do.

甚至更高一级,您描述的功能与rsyslogd等功能非常相似。

回答by Nicholas Wilson

Not so obvious! socat doesn't have any options for changing what it does with the connection halfway through. That means you'll have to be a little bit sneaky. Use socat with the output as STDOUT, and pipe to this script:

没那么明显!socat 没有任何选项可以在中途更改它对连接的作用。这意味着你必须有点偷偷摸摸。将 socat 与输出作为 STDOUT 一起使用,并通过管道传输到此脚本:

#!/bin/bash
rv=0
while [ $rv -lt 1 ]
do  
  NEXT_STOP=`date +%s --date "$DELAY second"`
  while [ "$(date +%s)" -lt "$NEXT_STOP" ] && [ $rv -lt 1 ]
  do
    head -q - >> /var/ais/out_v4.txt
    rv=$?
  done
  mv /var/ais/out_v4.txt "/var/ais/_socat_received/"$(date +"%Y-%m-%d-%T")"__out_v4.txt"
done

Totally untested, but looks reasonable?

完全未经测试,但看起来合理?

socat -u TCP-LISTEN:6116,reuseaddr,keepalive,rcvbuf=131071,reuseaddr STDOUT | ./thescript.sh