我们的产品OS有Solaris和Linux两种, 故障定位时经常需要现场的同学抓包。 为了方便抓包, 用shell做了一个抓包脚本。
主要功能如下:
1、自动识别OS类型, 使用对应的抓包命令, Solaris是snoop命令, Linux是tcpdump命令;
2、提示方式输入网卡、IP地址和端口;
3、可支持实时抓包和后台定时抓包(15分钟生成一个抓包文件)两种模式。
贴出完整代码, 如果这个工具对你有用, 请记得点赞!
#!/bin/sh
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#
# A tool to capture TCP/IP packets automatically
#
# Author: Gary Li
#
# E-mail: Gang.H.LI@nokia-sbell.com
#
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
OS=`uname`
PCAP_CMD=""
PARA_I=""
PARA_F=""
GZIP=""
PING_CMD=""
PARA_H=""
NICS=""
if [ "$OS" = "SunOS" ]; then
PCAP_CMD="/usr/sbin/snoop"
PARA_I="-d"
PARA_F="-o"
GZIP="/usr/bin/gzip"
PING_CMD="/usr/sbin/ping"
IFCONFIG_CMD="/usr/sbin/ifconfig"
NICS=`$IFCONFIG_CMD -a|grep -v lo0|grep flags|cut -f1 -d:`
elif [ "$OS" = "Linux" ]; then
PCAP_CMD="/usr/sbin/tcpdump"
PARA_I="-i"
PARA_F="-w"
GZIP="/bin/gzip"
PING_CMD="/bin/ping -c 1"
PARA_H="host"
IFCONFIG_CMD="/sbin/ifconfig"
NICS=`$IFCONFIG_CMD -a|grep ' Link encap:Ethernet'|awk '{print $1}'`
else
echo "Wrong OS type."
exit 1
fi
echo $0 | grep '^\.' >/dev/null 2>&1
if [ "$?" = "0" ]; then
CMD=`pwd`/$0
CMD=`echo $CMD | sed 's/\.\///'`
else
CMD=$0
fi
BINDIR=`dirname $CMD`
AskNicName() {
NIC="notValidInput"
while [ "$NIC" = "notValidInput" ]; do
echo "Please select NIC from below list then press Enter."
echo $NICS
echo "Press Enter directly for any: "
read ANS
if [ "$ANS" = "q" ] || [ "$ANS" = "Q" ] || [ "$ANS" = "quit" ] || [ "$ANS" = "exit" ]; then
exit 0
fi
if [ "X$ANS" = "X" ]; then
NIC="any"
if [ "$OS" = "SunOS" ]; then
echo "Not support any by snoop."
NIC="notValidInput"
fi
else
$IFCONFIG_CMD $ANS >/dev/null 2>&1
if [ "$?" = "0" ]; then
NIC=$ANS
else
echo "Input is not valid. Please retry. "
NIC="notValidInput"
fi
fi
done
}
AskIPAddr() {
IPADDR="notValidInput"
while [ "$IPADDR" = "notValidInput" ]; do
echo "Please input IP Address (Default is none): "
read ANS
if [ "$ANS" = "q" ] || [ "$ANS" = "Q" ] || [ "$ANS" = "quit" ] || [ "$ANS" = "exit" ]; then
exit 0
fi
if [ "X$ANS" = "X" ] || [ "$ANS" = "NONE" ] || [ "$ANS" = "none" ]; then
IPADDR=""
else
#$PING_CMD $ANS >/dev/null 2>&1
CHK_RES=`ValidIPAddr $ANS`
if [ "$CHK_RES" = "valid" ]; then
IPADDR="$PARA_H $ANS"
else
echo "Input is not valid. Please retry. "
IPADDR="notValidInput"
fi
fi
done
}
ValidIPAddr() {
if echo "$1" | { IFS=. read a b c d e;
test "$a" -ge 0 2>/dev/null && test "$a" -le 255 2>/dev/null &&
test "$b" -ge 0 2>/dev/null && test "$b" -le 255 2>/dev/null &&
test "$c" -ge 0 2>/dev/null && test "$c" -le 255 2>/dev/null &&
test "$d" -ge 0 2>/dev/null && test "$d" -le 255 2>/dev/null &&
test -z "$e" 2>/dev/null; }; then
echo valid
else
echo invalid
fi
}
AskPortNum() {
PORT="notValidInput"
while [ "$PORT" = "notValidInput" ]; do
echo "Please input Port (Default is none): "
read ANS
if [ "$ANS" = "q" ] || [ "$ANS" = "Q" ] || [ "$ANS" = "quit" ] || [ "$ANS" = "exit" ]; then
exit 0
fi
if [ "X$ANS" = "X" ] || [ "$ANS" = "NONE" ] || [ "$ANS" = "none" ]; then
PORT=""
else
if [ $ANS -eq $ANS ] 2>/dev/null; then
if [ "x$IPADDR" = "x" ]; then
PORT="port "$ANS
else
PORT="and port "$ANS
fi
else
echo "Input is not valid. Please retry. "
PORT="notValidInput"
fi
fi
done
}
AddIntoCron() {
TASK_15MIN="0,15,30,45 0-23 * * * $CMD $PARA_I $NIC $IPADDR $PORT > $BINDIR/output.log 2>&1"
DumpOldCron
echo "$TASK_15MIN" >> /var/tmp/mycron.new
crontab /var/tmp/mycron.new
CleanTmpFile
echo "Enabled."
}
DisableCron() {
DumpOldCron
crontab /var/tmp/mycron.new
CleanTmpFile
CloseExistProcess
echo "Disabled."
}
DumpOldCron() {
touch /var/tmp/mycron.old
crontab -l > /var/tmp/mycron.old 2>/dev/null
grep -v "$CMD" /var/tmp/mycron.old > /var/tmp/mycron.new 2>/dev/null
}
CleanTmpFile() {
rm -f /var/tmp/mycron.new
rm -f /var/tmp/mycron.old
}
CloseExistProcess() {
if [ `ps -ef|grep -v grep|grep "$PCAP_CMD"|grep "AUTOPCAP"|wc -l` -gt 0 ]; then
ps -ef|grep -v grep|grep "$PCAP_CMD"|grep "AUTOPCAP"|awk '{print $2}'|xargs kill -INT >/dev/null 2>&1
fi
}
StartPcap() {
DT=`date '+%Y-%m-%d-%H-%M-%S'`
FN=$BINDIR"/AUTOPCAP_"$DT".pcap"
if [ "$1" = "$PARA_I" ]; then
NIC=$2
fi
if [ "$NIC" != "any" ]; then
$IFCONFIG_CMD $NIC >/dev/null 2>&1
if [ "$?" != "0" ]; then
echo $NIC" is not a valid NIC."
exit 1
fi
fi
CloseExistProcess
echo "Start to capture packets on "$NIC" into file "$FN
echo "Press Ctrl+c to stop this session."
$PCAP_CMD $PARA_F $FN $* >/dev/null 2>&1
#$PCAP_CMD $PARA_F $FN $PARA_I $NIC $IPADDR $PORT >/dev/null 2>&1
$GZIP $FN >/dev/null 2>&1
}
##### Main #####
if [ $# -ge 1 ]; then
if [ "$1" = "enable" ]; then
AskNicName
AskIPAddr
AskPortNum
AddIntoCron
elif [ "$1" = "disable" ]; then
DisableCron
else
if [ "$1" = "$PARA_I" ]; then
NIC=$2
StartPcap $*
elif [ "$1" = "-h" ] || [ "$1" = "-H" ]; then
echo "Usage:"
echo "./autopcap.sh -- no argument means to capture now"
echo "./autopcap.sh [enable|disable] -- enable or disable capturing in background. Generate a file per 15 min"
echo ""
exit 0
else
echo "Wrong arguments."
exit 1
fi
fi
else
AskNicName
AskIPAddr
AskPortNum
StartPcap $PARA_I $NIC $IPADDR $PORT
fi
exit 0