2017-05-17 21:23:19 zd199218 阅读数 3227
  • 红帽Linux系统企业内部实训

    本课程基于红帽企业版Linux即RHEL(RHEL是Red Hat Enterprise Linux的缩写),在课程中讲解了RHEL的安装、基础网络命令、网卡设置、文件与目录管理、进程与线程管理、VI编辑器、用户与权限、软件包管理、如何地在Linux上搭建Discuz论坛,以及磁盘管理技术、引导故障排错、root密码解锁、NFS、SAMBA、FTP、VNC服务等。

    18484 人正在学习 去看看 杨璞

背景:

现阶段手头的一个自研的流式计算平台在完善监控体系,对机器资源负载、机器上任务资源消耗进行统计和上报,这里对Linux下获取网卡上限的方法进行梳理。

说明:这里的网卡最大带宽指的是物理网卡的带宽最大值
现阶段是使用系统提供的命令ethtool获取网卡最大值,具体命令如下:
ethtool eth1 | grep Speed

//1000M网卡机器中,ethtool命令的执行结果:
[root@WSC-155-91 ~]# ethtool eth1
Settings for eth1:
        Supported ports: [ TP ]
        Supported link modes:   10baseT/Half 10baseT/Full 
                                100baseT/Half 100baseT/Full 
                                1000baseT/Full 
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full 
                                100baseT/Half 100baseT/Full 
                                1000baseT/Full 
        Advertised pause frame use: Symmetric
        Advertised auto-negotiation: Yes
        Speed: 1000Mb/s  // 网卡流速上限
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 1
        Transceiver: internal
        Auto-negotiation: on
        MDI-X: off
        Supports Wake-on: pumbg
        Wake-on: g
        Current message level: 0x00000007 (7)
        Link detected: yes
[root@WSC-155-91 ~]# ethtool eth1 | grep Speed
        Speed: 1000Mb/s

-------------------------------------------------------------------------------------

//10000M网卡机器中,ethtool命令的执行结果:
[root@WSC-32-134 ~]# ethtool eth1      
Settings for eth1:
        Supported ports: [ TP ]
        Supported link modes:   100baseT/Full 
                                1000baseT/Full 
                                10000baseT/Full 
        Supported pause frame use: No
        Supports auto-negotiation: Yes
        Advertised link modes:  100baseT/Full 
                                1000baseT/Full 
                                10000baseT/Full 
        Advertised pause frame use: Symmetric
        Advertised auto-negotiation: Yes
        Speed: 10000Mb/s  // 网卡流速上限
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 0
        Transceiver: external
        Auto-negotiation: on
        MDI-X: Unknown
        Supports Wake-on: umbg
        Wake-on: g
        Current message level: 0x00000007 (7)
                               drv probe link
        Link detected: yes
[root@WSC-32-134 ~]# ethtool eth1 | grep Speed
        Speed: 10000Mb/s
2019-04-12 16:58:57 xclshwd 阅读数 1268
  • 红帽Linux系统企业内部实训

    本课程基于红帽企业版Linux即RHEL(RHEL是Red Hat Enterprise Linux的缩写),在课程中讲解了RHEL的安装、基础网络命令、网卡设置、文件与目录管理、进程与线程管理、VI编辑器、用户与权限、软件包管理、如何地在Linux上搭建Discuz论坛,以及磁盘管理技术、引导故障排错、root密码解锁、NFS、SAMBA、FTP、VNC服务等。

    18484 人正在学习 去看看 杨璞

1、前言

        针对安防行业,实时通过4G上传实时码流推送到监控中心,网络带宽好的时,上传一定分辨率和码率的实时流,通过RTP协议上传到监控中心,可以实时观看,延迟不大;但是当网络不好时,再上传固定码流和分辨率下,监控中心延迟非常大,那么怎么能动态改变分辨率和码率实时上传码流,监控中心实时观看呢。目前可通过/proc/net/dev 来获取实时发送和接收状态,从而可以有效监控和改变分辨率和码率。

2、原理

        Linux提供的LKM机制可以使我们通过proc伪文件系统来获取Linux内核信息,而通过proc/net/dev我们可以实时获取网络适配器及统计信息。抛开复杂的概念,简单说就是我们可以利用proc/net/dev来获取网卡的网速及网络包的收发情况。这里我们主要关心Receive和Transmit项的bytes项。同样网卡的流量,丢包率可以通过/proc/net/dev文件来读取。 ifstat获取网卡数据就是读取的/proc/net/dev系统来的。

bytes: 接口发送或接收的数据的总字节数
packets: 接口发送或接收的数据包总数
errs: 由设备驱动程序检测到的发送或接收错误的总数
drop: 设备驱动程序丢弃的数据包总数
fifo: FIFO缓冲区错误的数量
frame: 分组帧错误的数量
colls: 接口上检测到的冲突数
compressed: 设备驱动程序发送或接收的压缩数据包数
carrier: 由设备驱动程序检测到的载波损耗的数量
multicast: 设备驱动程序发送或接收的多播帧数
 

3、实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>  
#include <sys/stat.h> 
#include <sys/ioctl.h> 
#include <sys/socket.h>
#include <sys/wait.h> 
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h> 
#include <pthread.h>   
#include <dirent.h> 
#include <time.h>
#include <fcntl.h> 
#include <errno.h>

int GetNetRate(FILE* fd,char *interface,long *recv,long *send)
{
	char tmpBuf[1024];
	char *p;
	char flow[32];
	int i = 0;	
	char tempstr[16][16]={0};
	
	memset(tmpBuf,0,sizeof(tmpBuf));
	memset(tempstr,0,sizeof(tempstr));
	fseek(fd, 0, SEEK_SET);
	int nBytes = fread(tmpBuf,1, sizeof(tmpBuf)-1,fd);
	if (-1 == nBytes)
	{
		printf("fread error");
		fclose(fd);
		return -1;
	}
	tmpBuf[nBytes] = '\0';
	char* pDev = strstr(tmpBuf, interface);
	if (NULL == pDev)
	{
		printf("don't find dev %s\n", interface);
		fclose(fd);
		return -1;
	}
	sscanf(pDev,"%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t",\
	tempstr[0],tempstr[1],tempstr[2],tempstr[3],tempstr[4],tempstr[5],tempstr[6],tempstr[7],tempstr[8],tempstr[9],tempstr[10],tempstr[11]);
	*recv = atol(tempstr[1]);		
	*send = atol(tempstr[9]);	
}

 
int main(int argc, char** argv)  
 { 
    struct timeval tv_now,tv_pre;
	char netdevice[16]={0};
	int nDevLen; 	
	long recvpre = 0,recvcur = 0;
	long sendpre = 0,sendcur = 0;
	double sendrate;
	double recvrate;
	
	if(argc != 2)
	{
		printf("Usage: netrate <network device>\n");
		exit(0);
	}
	
	nDevLen = strlen(argv[1]);
	if (nDevLen < 1 || nDevLen > 10)
	{
		printf("unkown device\n");
		exit(0);
	}
	sprintf(netdevice,"%s",argv[1]);
	
	FILE* fd = fopen("/proc/net/dev","r+");
	if (NULL == fd)
	{
		printf("/proc/net/dev not exists!\n");
		return -1;
	}
	while(1)
	{	
		gettimeofday(&tv_pre,NULL);
		GetNetRate(fd,netdevice,&recvpre,&sendpre);
		sleep(2);
		gettimeofday(&tv_now,NULL);
		GetNetRate(fd,netdevice,&recvcur,&sendcur);
		recvrate= (recvcur - recvpre)/(1024*(tv_now.tv_sec+tv_now.tv_usec*0.000001-tv_pre.tv_sec+tv_pre.tv_usec*0.000001));
		if(recvrate<0)
		{
			recvrate = 0;
		}
		sendrate= (sendcur - sendpre)/(1024*(tv_now.tv_sec+tv_now.tv_usec*0.000001-tv_pre.tv_sec+tv_pre.tv_usec*0.000001));
		if(sendrate<0)
		{
			sendrate = 0;
		}
		system("clear");
		printf("NetWorkRate Statistic Verson 0.0.1\n");
		printf("Net Device	receive rate	send rate\n");
		printf("%-10s\t%-6.2fKB/sec\t%-6.2fKB/sec\n",netdevice,recvrate,recvrate);
	}
	fclose(fd);
    return 0;
}

代码参考:https://blog.csdn.net/dosthing/article/details/80384541 

 

2018-10-18 17:49:06 weixin_36511527 阅读数 2675
  • 红帽Linux系统企业内部实训

    本课程基于红帽企业版Linux即RHEL(RHEL是Red Hat Enterprise Linux的缩写),在课程中讲解了RHEL的安装、基础网络命令、网卡设置、文件与目录管理、进程与线程管理、VI编辑器、用户与权限、软件包管理、如何地在Linux上搭建Discuz论坛,以及磁盘管理技术、引导故障排错、root密码解锁、NFS、SAMBA、FTP、VNC服务等。

    18484 人正在学习 去看看 杨璞

客服反馈服务器带宽满。之前每天10M就够了,现在20/30都不够,而且是升级到多少,就满多少,包括晚上3/4点都是一直满。

首先需要确定是哪一张网卡的带宽跑满

可以通过sar -n DEV 1 5命令来获取网卡级别的流量图,命令中 1 5 表示每一秒钟取 1 次值,一共取 5 次。

命令执行后会列出每个网卡这 5 次取值的平均数据,根据实际情况来确定带宽跑满的网卡名称。阿里云服务器,默认情况下 eth0 为内网网卡,eth1 为外网网卡。

如上图所示,发现确实是eth1也就是外网网卡占用了绝大部分的流量。

接下来使用 iftop 工具排查具体占用流量的IP和端口

1、服务器内部安装 iftop 流量监控工具:

	yum install iftop -y

2、服务器外网带宽被占满时,如果通过远程无法登陆,可通过阿里云终端管理进入到服务器内部,运行下面命令查看流量占用情况:

	iftop -i eth1 -P

注:-P 参数会将请求服务的端口显示出来,也就是说是通过服务器哪个端口建立的连接,看内网流量执行 iftop -i eth0 -P 命令。

发现大量IP都是自己的服务器IP,自己在请求自己,这是怎么回事呢

通过访问日志去看一下原因,发现都是自己的网站在请求,排查后,是自己的代码问题

参考文档:

http://bbs.qcloud.com/forum.php?mod=viewthread&tid=20893&highlight=%E5%B8%A6%E5%AE%BD

(备用连接http://note.youdao.com/noteshare?id=69cabad87beb4c63df324171fbfdd0d2&sub=B30C4C34F7BF4251BB9BE91471E883C5

http://www.02405.com/soft/linux/1055.html

(备用连接http://note.youdao.com/noteshare?id=8424d9c906b105b259ed34c5e9cc1414&sub=78FB68DBFB7042D9B197E0C577857D92

2017-05-02 18:15:16 ternence_hsu 阅读数 779
  • 红帽Linux系统企业内部实训

    本课程基于红帽企业版Linux即RHEL(RHEL是Red Hat Enterprise Linux的缩写),在课程中讲解了RHEL的安装、基础网络命令、网卡设置、文件与目录管理、进程与线程管理、VI编辑器、用户与权限、软件包管理、如何地在Linux上搭建Discuz论坛,以及磁盘管理技术、引导故障排错、root密码解锁、NFS、SAMBA、FTP、VNC服务等。

    18484 人正在学习 去看看 杨璞
NetHogs介绍
NetHogs是一款开源、免费的,终端下的网络流量监控工具,它可监控Linux的进程或应用程序的网络流量。NetHogs只能实时监控进程的网络带宽占用情况。NetHogs支持IPv4和IPv6协议,支持本地网卡以及PPP链接。
NetHogs是一个小型的’net top’工具,不像大多数工具那样拖慢每个协议或者是每个子网的速度而是按照进程进行带宽分组.NetHogs NetHogs不需要依赖载入某个特殊的内核模块. 如果发生了网络阻塞你可以启动NetHogs立即看到哪个PID造成的这种状况.这样就很容易找出哪个程序跑飞了然后突然占用你的带宽。

NetHogs下载

Ubuntu下NetHogs安装
sudo apt-get install nethogs

NetHogs使用
root@ternence-All-Series# nethogs


NetHogs提供交互式控制指令:
m : Cycle between display modes (kb/s, kb, b, mb) 切换网速显示单位
r : Sort by received. 按接收流量排序
s : Sort by sent. 按发送流量排序
q : Quit and return to the shell prompt. 退出NetHogs命令工具

NetHogs 命令行参数
常用的参数:
-d delay for refresh rate. 数据刷新时间 如nethogs -d 1 就是每秒刷新一次
-h display available commands usage. 显示命名帮助、使用信息
-p sniff in promiscious mode (not recommended).
-t tracemode.
-V prints Version info.
演示例子:
#5秒刷新一次数据
nethogs -d 5
#监控网卡eth0数据
nethogs eth0
#同时监视eth0和eth1接口
nethogs eth0 eth1
#将监控日志写入日志文件
nethogs >>test.log
2018-02-08 13:30:00 weixin_34395205 阅读数 68
  • 红帽Linux系统企业内部实训

    本课程基于红帽企业版Linux即RHEL(RHEL是Red Hat Enterprise Linux的缩写),在课程中讲解了RHEL的安装、基础网络命令、网卡设置、文件与目录管理、进程与线程管理、VI编辑器、用户与权限、软件包管理、如何地在Linux上搭建Discuz论坛,以及磁盘管理技术、引导故障排错、root密码解锁、NFS、SAMBA、FTP、VNC服务等。

    18484 人正在学习 去看看 杨璞

在windows以下。我们能够看到360或者是qq安全卫士的“安全球”。上面显示实时的网速情况。那么在linux里面怎样获取网卡的实时网速?事实上原理非常easy,读取须要获取网速的网卡在某段时间dT内流量的变化dL,那么实时网速就出来了,Speed = dL / dt。

linux在ifaddrs.h中提供了函数:

/* Create a linked list of `struct ifaddrs' structures, one for each
   network interface on the host machine.  If successful, store the
   list in *IFAP and return 0.  On errors, return -1 and set `errno'.
            
   The storage returned in *IFAP is allocated dynamically and can
   only be properly freed by passing it to `freeifaddrs'.  */
extern int getifaddrs (struct ifaddrs **__ifap) __THROW;
           
/* Reclaim the storage allocated by a previous `getifaddrs' call.  */
extern void freeifaddrs (struct ifaddrs *__ifa)  __THROW;

系统会创建一个包括本机全部网卡信息链表,然后我们就能够在这个链表里面获取我们想要的信息。

/* The `getifaddrs' function generates a linked list of these structures.
   Each element of the list describes one network interface.  */
struct ifaddrs
{
  struct ifaddrs *ifa_next; /* Pointer to the next structure.  */

  char *ifa_name;       /* Name of this network interface.  */
  unsigned int ifa_flags;   /* Flags as from SIOCGIFFLAGS ioctl.  */

  struct sockaddr *ifa_addr;    /* Network address of this interface.  */
  struct sockaddr *ifa_netmask; /* Netmask of this interface.  */
  union
  {
    /* At most one of the following two is valid.  If the IFF_BROADCAST
       bit is set in `ifa_flags', then `ifa_broadaddr' is valid.  If the
       IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid.
       It is never the case that both these bits are set at once.  */
    struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */
    struct sockaddr *ifu_dstaddr; /* Point-to-point destination address.  */
  } ifa_ifu;
  /* These very same macros are defined by <net/if.h> for `struct ifaddr'.
     So if they are defined already, the existing definitions will be fine.  */
# ifndef ifa_broadaddr
#  define ifa_broadaddr ifa_ifu.ifu_broadaddr
# endif
# ifndef ifa_dstaddr
#  define ifa_dstaddr   ifa_ifu.ifu_dstaddr
# endif 
        
  void *ifa_data;       /* Address-specific data (may be unused).  */
};
另外这个链表我们是能够提前用ioctl来筛选的,能够通过ifa_name和ifa_flags来确定ifa_ifu里面究竟选用那个union。只是这次我们是来測量实时网速的,不必要关心这个。

我们须要关心的是ifa_data这个项。关于这个项我百度了非常多。一直没有发现他究竟应该属于哪个结构体的。

后来无意在http://blog.chinaunix.net/uid-22832715-id-292763.html发现有相似的,可是我找不到头文件在那。所以后来干脆我直接把他放到我的头文件中面;

struct if_data{
	/* generic interface information */
	u_char	ifi_type;	/* ethernet, tokenring, etc */
	u_char	ifi_addrlen;	/* media address length */
	u_char	ifi_hdrlen;	/* media header length */
	u_long	ifi_mtu;	/* maximum transmission unit */
	u_long	ifi_metric;	/* routing metric (external only) */
	u_long	ifi_baudrate;	/* linespeed */
	/* volatile statistics */
	u_long	ifi_ipackets;	/* packets received on interface */
	u_long	ifi_ierrors;	/* input errors on interface */
	u_long	ifi_opackets;	/* packets sent on interface */
	u_long	ifi_oerrors;	/* output errors on interface */
	u_long	ifi_collisions;	/* collisions on csma interfaces */
	u_long	ifi_ibytes;	/* total number of octets received */
	u_long	ifi_obytes;	/* total number of octets sent */
	u_long	ifi_imcasts;	/* packets received via multicast */
	u_long	ifi_omcasts;	/* packets sent via multicast */
	u_long	ifi_iqdrops;	/* dropped on input, this interface */
	u_long	ifi_noproto;	/* destined for unsupported protocol */
	struct	timeval ifi_lastchange;/* last updated */
};
刚刚開始我就打印了ifi_iobytes,ifi_obytes这两个项,无论我怎么下载和上次文件,这两个量都是0。

纠结了我半天。我就直接把全部变量都打印出来。发现ifi_mtu,ifi_metric,ifi_baudrate跟ifconfig eth0输出的数据非常像。

[15:12 @ ~/program/netspeed]$ ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:22:15:67:F8:16  
          inet addr:210.42.158.204  Bcast:210.42.158.255  Mask:255.255.255.0
          inet6 addr: fe80::222:15ff:fe67:f816/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:917978 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1132894 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:132866544 (126.7 MiB)  TX bytes:1250785627 (1.1 GiB)
          Interrupt:29 Base address:0x4000 
慢慢的我知道了规律,struct ifaddrs里面的ifa_data前四个字(32位)以此是发送数据包数。接收数据包数,发送字节数,接收字节数。

我就又一次调整了struct if_data的结构体,因为后面的数据全为0,我就保留了4项:

struct if_data
{   
    /*  generic interface information */
    u_long ifi_opackets;    /*  packets sent on interface */
    u_long ifi_ipackets;    /*  packets received on interface */
    u_long ifi_obytes;      /*  total number of octets sent */
    u_long ifi_ibytes;      /*  total number of octets received */
};  
測试OK。

[15:17 @ ~/program/netspeed]$ ./netspeed 
Get eth0 Speed                  [OK]
eth0: Up Speed: 1.671066 MB/s || Down Speed: 0.036335 MB/s 
附上我已经封装好的代码:

int get_if_dbytes(struct if_info* ndev)
{   
    assert(ndev);
    
    struct ifaddrs *ifa_list = NULL;
    struct ifaddrs *ifa = NULL;
    struct if_data *ifd = NULL;
    int     ret = 0;
    
    ret = getifaddrs(&ifa_list);
    if(ret < 0) { 
        perror("Get Interface Address Fail:");
        goto end;
    }   
    
    for(ifa=ifa_list; ifa; ifa=ifa->ifa_next){
        if(!(ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_RUNNING))
            continue;

        if(ifa->ifa_data == 0)
            continue;
        
        ret = strcmp(ifa->ifa_name,ndev->ifi_name);
        if(ret == 0){
           ifd = (struct if_data *)ifa->ifa_data;
           
           ndev->ifi_ibytes = ifd->ifi_ibytes;
           ndev->ifi_obytes = ifd->ifi_obytes;
           break;
        }
    }

    freeifaddrs(ifa_list);
end:
    return (ret ? -1 : 0);
}

int get_if_speed(struct if_speed *ndev)
{
    assert(ndev); 

    struct if_info *p1=NULL,*p2=NULL;

    p1 = (struct if_info *)malloc(sizeof(struct if_info));
    p2 = (struct if_info *)malloc(sizeof(struct if_info));
    bzero(p1,sizeof(struct if_info));
    bzero(p2,sizeof(struct if_info));

    strncpy(p1->ifi_name,ndev->ifs_name,strlen(ndev->ifs_name));
    strncpy(p2->ifi_name,ndev->ifs_name,strlen(ndev->ifs_name));

    int ret = 0;
    ret = get_if_dbytes(p1);
    if(ret < 0)     goto end;
    usleep(ndev->ifs_us);
    ret = get_if_dbytes(p2);
    if(ret < 0)     goto end;

    ndev->ifs_ispeed = p2->ifi_ibytes - p1->ifi_ibytes;
    ndev->ifs_ospeed = p2->ifi_obytes - p1->ifi_obytes;

end:
    free(p1);
    free(p2);

    return 0;
}

头文件:

#ifndef __TSPEED_H__
#define __TSPEED_H__

#ifdef __cplusplus
extern "C"
{
#endif
    
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <error.h>

    /* For "open" function */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct if_data
{   
    /*  generic interface information */
    u_long ifi_opackets;    /*  packets sent on interface */
    u_long ifi_ipackets;    /*  packets received on interface */
    u_long ifi_obytes;      /*  total number of octets sent */
    u_long ifi_ibytes;      /*  total number of octets received */
};
    
struct if_info
{   
    char ifi_name[16];
    unsigned long ifi_ibytes;
    unsigned long ifi_obytes;
};
struct if_speed
{   
    char ifs_name[16];
    unsigned long ifs_ispeed;
    unsigned long ifs_ospeed;
    unsigned long ifs_us;
};

extern int get_if_dbytes(struct if_info *ndev);
extern int get_if_speed(struct if_speed *ndev);

#ifdef __cplusplus
}
#endif

#endif
測试代码:

int main (int argc, char **argv)
{
    struct if_speed ndev;
    int ret = 0;

    bzero(&ndev,sizeof(ndev));
    sprintf(ndev.ifs_name,"eth0");

    ndev.ifs_us = 100000;

    printf("Get %s Speed");
    ret = get_if_speed(&ndev);
    if(ret < 0)
        printf("\t\t\t[Fail]\n");
    else
        printf("\t\t\t[OK]\n");
    float ispeed ,ospeed;
    while(1){
        ispeed = ndev.ifs_ispeed * 1.0/(ndev.ifs_us/1000 * 0.001);
        ospeed = ndev.ifs_ospeed * 1.0/(ndev.ifs_us/1000 * 0.001);

        printf("%s: Up Speed: %f MB/s || Down Speed: %f MB/s                   \r",
                ndev.ifs_name,ispeed/(1024.0*1024.0),ospeed/(1024.0*1024.0));

        get_if_speed(&ndev);
    }


    return 0;
} /* ----- End of main() ----- */

可能你有更好的获取网速的办法,求留言指点!
没有更多推荐了,返回首页