bash 脚本:在远程服务器上捕获 tcp 流量有时有效,有时失败。没有错误

bash 脚本:在远程服务器上捕获 tcp 流量有时有效,有时失败。没有错误

背景

我正在远程服务器上运行 BusyBox。

我有一个 bash 脚本,它执行两件事:
1. 通过 ssh,启动一个子进程以使用 tcpdump 命令监视 tcp 流量。将结果保存到文件中 - 在远程计算机或本地计算机上。两者都尝试过。
2. 启动第二个子进程来生成 TCP 流量。

代码片段:

#html_tcpdumpfile="$(ssh remotemachine.mydomain.net \"mktemp\")"
html_tcpdumpfile=$(mktemp)

test_steps=(
    #"{ ssh remotemachine.mydomain.net \"timeout -t 20 tcpdump -nvi eth0 port 5060 > "$html_tcpdumpfile" \" ; }" 
    "{ ssh remotemachine.mydomain.net \"timeout -t 20 tcpdump -i eth0 port 5060 \"> $html_tcpdumpfile; }"   
    "{ ssh remotemachine.mydomain.net \"timeout -t 15 cat /tmp/htmlemail.txt | /etc/postfix/process_email.py \"; }"
 )
pids=()
for index in ${!test_steps[@]}; do       
      (echo "${test_steps[$index]}" | bash) &
      pids[${index}]=$!
      echo "$pids[${index}] is the pid"
done

#shouldn't really need this because of the timers but... just in case...
for pid in ${pids[*]}; 
do   
  wait $pid; 
done;
# ============ ANALYZE TEST RESULTS
echo "========== html_tcpdumpfile CONTENTS ============="
cat $html_tcpdumpfile
echo "========== html_tcpdumpfile CONTENTS ============="

问题

有时,tcpdump 命令不会捕获任何内容,而有时却会捕获任何内容。捕获失败时没有错误消息。

到目前为止我尝试过的

  1. 正如您所看到的,我尝试更改远程计算机和本地计算机之间转储文件的位置。这似乎没有什么区别。

  2. 我已经证明 TCP 流量总是生成的...每次运行脚本时,因为我打开了另一个 ssh 会话,并且我可以看到正在生成的流量。只是我的脚本间歇性地无法捕获它。

  3. 我尝试将 tcp 会话的超时值增加到很大,以确保给它足够的时间。但我不认为这是问题所在。

任何建议,将不胜感激。谢谢。

编辑1

我尝试在启动每个子进程之间引入睡眠:

pids=()
for index in ${!test_steps[@]}; do       
      (echo "${test_steps[$index]}" | bash) &
      sleep 5
      pids[${index}]=$!
      echo "$pids[${index}] is the pid"
done

但这也没有什么区别。

编辑2

我将 tcpdump 命令更改为如下所示:

test_steps=(     
    "{ ssh remotemachine.mydomain.net \"timeout -t 30 tcpdump -nlc 100 -i eth0 port 5060 \"> $rtf_tcpdumpfile; }" 
    "{ ssh remotemachine.mydomain.net \"timeout -t 20 tail -f /var/log/messages \" > $syslog; }"    
    "{ ssh remotemachine.mydomain.net \"timeout -t 15 cat /tmp/htmlemail.txt | /etc/postfix/process_email.py \"; }"
 )

tcpdump仍然间歇性地捕获失败,但是……有趣的是syslog总是能够成功捕获。 (Python 脚本在调用时实际上会写入系统日志,因此我可以看到/证明该脚本正在运行)

答案1

首先,如果您正在处理空间有限的设备/物联网,我将处理调用方的输出,即在命令后使用 > ,ssh如下所示

ssh "command" > output.txt

至于tcpdump我不会一直把它作为一项政策而取消,冒着失去缓冲的风险。您可能因此而没有输出。

我会对捕获的数据包进行限制。我也尽量不解决DNS问题。例如,捕获 100 个数据包:

tcpdump -nc 100 -i eth0 port 5600

当您将捕获文件存储在本地系统上时,您应该只cat在本地运行,而不是远程和本地运行。

同样,当您同时运行tcpdumpcat远程运行时,您将同时启动两者,并且远程和本地cat都不会显示任何内容。

根据@MarkPlotnick的建议,我还添加了-l使其tcpdump行缓冲。这可能会消除对该选项的需要-c。我会同时使用。

所以我会将该脚本更改为:

#!/bin/bash
html_tcpdumpfile=$(mktemp)

ssh remotemachine.mydomain.net "timeout -t 20 tcpdump -nlc 100 -i eth0  port 5060 " > $html_tcpdumpfile

cat $html_tcpdumpfile

rm $html_tcpdumpfile

或者我们甚至可能不需要显式创建临时文件:

#!/bin/bash

ssh remotemachine.mydomain.net "timeout -t 20 tcpdump -nlc 100 -i eth0  port 5060 " \
| less

最后,我建议删除所有创建的临时文件,特别是在远程端。

PS:评论中提到的OP远程系统是BusyBox,因此timeout选项与包中的不同coretutils。我还编辑了问题以提及 BusyBox。

相关内容