端口检测目的意义:

在网络入侵中,端口扫描几乎是所有网络入侵过程中的必然前奏,入侵者首先通过端口扫描来发现目标主机的操作系统类型,提供的服务和系统所使用的软件版本及其他各种相关信息,然后采取针对性的攻击手段。

因此对端口扫描进行检测,发现可能出现的攻击行为,可有效的配合入侵检测。

实现背景:

端口关联检测中最麻烦的部分应该是根据端口找所关联的进程,在网上找了很长时间,相关资料很少很少,倒是有个博主在讨论服务器netstat -anp无法获取部分所对应的进程pid和程序名是因为socket文件的inode太大,超过INT_MAX,对netstat源码 的实现提到了端口关联进程。故根据 安卓源码和netstat 源码 简单实现了对端口关联的检测。

相关知识简介:

Ubuntu下网络连接文件简介

由于本实验检测的是在ipv4ipv6下的tcpudp本连接中端口的关联情况,所以用到以下4种文件

1/proc/net/tcp文件,这里记录的是ipv4下所有tcp连接的情况。

2proc/net/tcp6文件,这里记录的是ipv6下所有tcp连接的情况。

3/proc/net/udp文件,这里记录的是ipv4下所有udp连接的情况。

4proc/net/udp6文件,这里记录的是ipv6下所有udp连接的情况。

4种文件都用到以下数据:

local_address 0101007F:0035本地IP(网络字节序):本地端口(网络字节序)

rem_address 00000000:0000远端IP(网络字节序):远端端口(网络字节序)

st 0A套接字状态,不同套接字对应不同的值

enum {

TCP_ESTABLISHED = 1,

TCP_SYN_SENT,// 2

TCP_SYN_RECV,// 3

TCP_FIN_WAIT1,// 4

TCP_FIN_WAIT2,// 5

TCP_TIME_WAIT,// 6

TCP_CLOSE,// 7

TCP_CLOSE_WAIT,// 8

TCP_LAST_ACK,// 9

TCP_LISTEN,// 0A

TCP_CLOSING,// 1 /* Now a valid state */

TCP_MAX_STATES /* leave at the end! */

};

tx_queue:rx_queue 00000000:00000000发送队列中的数据长度:状态是ESTABLISHED,表示的时接受队列中的数据长度,状态是LISTEN,表示已完成队列的长度

tr tm->when 00:00000000定时器类型,0表示没有启动定时器。1表示重传定时器,4表示持续定时器,2表示连接定时器、FIN_WAIT_2定时器或TCP保活定时器,3表 示TIME_WAIT定时器 retrnsmt 00000000超时重传次数

uid 0用户id

timeout 0持续定时器或者保活定时器周期性发送出去但未被确认的TCP段数目,收到ACK后清零。

inode 11864 1 0000000000000000 100 0 0 10 0

11864套接字对应的inode

1 sock结构的引用数

0000000000000000 sock结构的实例地址

100 RTO,单位是clock_t

0用来计算延时确认的估值

0快速确认数和是否启用的标志位的或运算结果

10当前拥塞窗口大小

0 如果满启动阀值大于0x7ffffff显示-1,否则表示慢启动阀值

Socket文件中inode分析

socket文件的inode存在于LinuxVFS虚拟文件系统中。VFS是一个异构文件系统之上的软件粘合层,可以让open()read()write()等系统调用不用关心底层的存储介质和文件系统类型就可以工作。通过VFS,一个抽象的通用访问接口屏蔽了底层文件系统和物理介质的差异性,每一种类型的文件系统代码都隐藏了实现的细节。对于VFS层和内核的其它部分而言,每一种类型的文件系统看起来都是一样的。

VFS inode和磁盘文件系统中的inode不同。比如ext2文件系统,它的inode位于磁盘上划分的块组中,每个inode 128字节。在分割扇区时,系统会先做出一堆inode供以后使用,inode的数量关系着系统中可以建立的文件及目录总数。磁盘上的每个文件都有且仅有一个inode,即使文件中没有数据,inode也存在。

VFS inode只存在于内存中,可以通过inode缓存访问。每个文件在VFS中都有相应的inode结点,包括普通文件、目录以及特殊文件,如socketpipe等。在需要某个文件的时候系统会在内存中为其建立相应的inode数据结构,建立的inode结构将形成一个链表,可以通过遍历这个链表去得到我们需要的文件结点。但是,VFS对于不同文件的inode号分配方式是不同的。

具体如下:

对于ext2等磁盘文件系统中的普通文件,每个文件在磁盘上都有对应的inode,该inode号也是已知的。在访问这些文件时,VFS会在内存中为这个文件分配VFS inode,将在磁盘文件系统中确定的inode号赋给inode结构。可见,一般普通文件的inode号都不会太大。

对于socket等特殊文件来说,并没有像磁盘文件一样的inode号的来源,内核在实现中维护了一个unsigned long型的静态变量来保存目前分配的inode号的最大值,新分配的inode号在此基础上加1来实现。这个静态变量的值会一直增大而不会减小,直至机器重启。

具体实现步骤:

1.通过网络文件查找获取端口数据

查找/proc/net/tcp/proc/net/udp/proc/net/tcp6/proc/net/udp6,从文件数据中提取所需要的本地ip,本地port,远端ip,远端port,套接字状态,发送队列中的数据长度,接收队列中的数据长度,以及套接字对应的inode

2.获取端口所关联的进程

  • 首先遍历所有的/proc/PID/fd目录,如果某个进程非本账号所有,则无权访问/proc/PID目录,跳过该PID,访问下一个。
  • 当某个/proc/PID/fd目录中有一个或多个socket句柄时,则读该/proc/PID目录下的cmdline文件,获取该进程的所执行程序的名称;同时,记录/proc/PID/fd目录下所有socket句柄的inode号。
  • 当所有进程遍历完成后,根据在网络文件proc/net/{tcp,udp,tcp6,udp6}获取的inode节点号,匹配你记录的所有socket句柄的inode后,若相等,则拥有该socket句柄的进程即为该端口关联的进程。
代码块分析

1.socket文件inode信息结构:

static struct prg_node {

struct prg_node *next;

int inode;

char name[PROGNAME_WIDTH];

}*prg_hash[PRG_HASH_SIZE];

name数组里存储进程pid以及进程名

2.ipv4 ipv6ip地址 网络字节序到主机字节序的转化。

static void addr2str(int,const void *,char * );

3./proc/net/tcp/proc/net/udp中连接数据的获取和输出。

static void ipv4(const char *,const char *);

4./proc/net/tcp6/proc/net/udp6中连接数据的获取和输出。

static void ipv6(const char *,const char *);

5.prg_node结构的信息存储于链表中。

static void prg_cache_add(int,char * );

6.遍历链表查看是否存在相等的inode节点,若有,将节点关联进程信息返回。

static const char *prg_cache_get(int );

7.清空链表。

static void prg_cache_clear( );

8.筛选类型为socket0000的句柄,并使用形-参返回对应的inode节点号。

static void extract_type_1_socket_inode(const char a[],long * );

static void extract_type_2_socket_inode(const char a[],long * );

9.实现遍历/proc/pid/fd和查看/proc/pid/cmdline获取信息。

static void prg_cache_load( );


代码如下:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <netdb.h>
#include <paths.h>
#include <pwd.h>
#include <getopt.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <dirent.h>
#define PROGNAME_WIDTH 20


#define PROGNAME_WIDTHs PROGNAME_WIDTH1(PROGNAME_WIDTH)
#define PROGNAME_WIDTH1(s) PROGNAME_WIDTH2(s)
#define PROGNAME_WIDTH2(s) #s

#define PRG_HASH_SIZE 211

#define PRG_HASHIT(x) ((x) % PRG_HASH_SIZE)

#ifndef LINE_MAX
#define LINE_MAX 4096
#endif

#define PATH_PROC	   "/proc"
#define PATH_FD_SUFF	"fd"
#define PATH_FD_SUFFl       strlen(PATH_FD_SUFF)
#define PATH_PROC_X_FD      PATH_PROC "/%s/" PATH_FD_SUFF
#define PATH_CMDLINE	"cmdline"
#define PATH_CMDLINEl       strlen(PATH_CMDLINE)

#define PRG_LOCAL_ADDRESS "local_address"
#define PRG_INODE	 "inode"
#define PRG_SOCKET_PFX    "socket:["
#define PRG_SOCKET_PFXl (strlen(PRG_SOCKET_PFX))
#define PRG_SOCKET_PFX2   "[0000]:"
#define PRG_SOCKET_PFX2l  (strlen(PRG_SOCKET_PFX2))
static char prg_cache_loaded = 0;

typedef union iaddr iaddr;
typedef union iaddr6 iaddr6;

static struct prg_node {
    struct prg_node *next;
    int inode;
    char name[PROGNAME_WIDTH];
} *prg_hash[PRG_HASH_SIZE];


union iaddr {
    unsigned u;
    unsigned char b[4];
};

union iaddr6 {
    struct {
        unsigned a;//unsigned int a; 无符号整型
        unsigned b;
        unsigned c;
        unsigned d;
    } u;
    unsigned char b[16];
};

static const char *state2str(unsigned state)
{
    switch(state){
    case 0x1: return "ESTABLISHED";
    case 0x2: return "SYN_SENT";
    case 0x3: return "SYN_RECV";
    case 0x4: return "FIN_WAIT1";
    case 0x5: return "FIN_WAIT2";
    case 0x6: return "TIME_WAIT";
    case 0x7: return "CLOSE";
    case 0x8: return "CLOSE_WAIT";
    case 0x9: return "LAST_ACK";
    case 0xA: return "LISTEN";
    case 0xB: return "CLOSING";
    default: return "UNKNowN";
    }
}

/* addr + : + port + \0 */
#define ADDR_LEN INET6_ADDRSTRLEN + 1 + 5 + 1

static void addr2str(int af,const void *addr,char *buf)
{
    if (inet_ntop(af,addr,buf,ADDR_LEN) == NULL) 
        *buf = '\0';
      return;
    
}
static void prg_cache_add(int inode,char *name)
{
    unsigned hi = PRG_HASHIT(inode);
    struct prg_node **pnp,*pn;

    prg_cache_loaded=2;
    for (pnp=prg_hash+hi;(pn=*pnp);pnp=&pn->next) {
	if (pn->inode==inode) {
	    /* Some warning should be appropriate here
	       as we got multiple processes for one i-node */
	    return;
	}
    }
    if (!(*pnp=malloc(sizeof(**pnp)))) 
	return;
    pn=*pnp;
    pn->next=NULL;
    pn->inode=inode;
    if (strlen(name)>sizeof(pn->name)-1) 
	name[sizeof(pn->name)-1]='\0';
    strcpy(pn->name,name);
}

static const char *prg_cache_get(int inode)
{
    unsigned hi=PRG_HASHIT(inode);
    struct prg_node *pn;

    for (pn=prg_hash[hi];pn;pn=pn->next)
	if (pn->inode==inode) return(pn->name);
    return("-");
}

static void prg_cache_clear(void)
{
    struct prg_node **pnp,*pn;

    if (prg_cache_loaded == 2)
	for (pnp=prg_hash;pnp<prg_hash+PRG_HASH_SIZE;pnp++)
	    while ((pn=*pnp)) {
		*pnp=pn->next;
		free(pn);
	    }
    prg_cache_loaded=0;
}


static void extract_type_1_socket_inode(const char lname[],long * inode_p) {

    /* If lname is of the form "socket:[12345]",extract the "12345"
       as *inode_p.  Otherwise,return -1 as *inode_p.
       */

    if (strlen(lname) < PRG_SOCKET_PFXl+3) *inode_p = -1;
    else if (memcmp(lname,PRG_SOCKET_PFX,PRG_SOCKET_PFXl)) *inode_p = -1;
    else if (lname[strlen(lname)-1] != ']') *inode_p = -1;
    else {
        char inode_str[strlen(lname + 1)];  /* e.g. "12345" */
        const int inode_str_len = strlen(lname) - PRG_SOCKET_PFXl - 1;
        char *serr;

        strncpy(inode_str,lname+PRG_SOCKET_PFXl,inode_str_len);
        inode_str[inode_str_len] = '\0';
        *inode_p = strtol(inode_str,&serr,0);
        if (!serr || *serr || *inode_p < 0 || *inode_p >= INT_MAX) 
            *inode_p = -1;
    }
}

static void extract_type_2_socket_inode(const char lname[],long * inode_p) {

    /* If lname is of the form "[0000]:12345",return -1 as *inode_p.
       */

    if (strlen(lname) < PRG_SOCKET_PFX2l+1) *inode_p = -1;
    else if (memcmp(lname,PRG_SOCKET_PFX2,PRG_SOCKET_PFX2l)) *inode_p = -1;
    else {
        char *serr;

        *inode_p=strtol(lname + PRG_SOCKET_PFX2l,0);
        if (!serr || *serr || *inode_p < 0 || *inode_p >= INT_MAX) 
            *inode_p = -1;
    }
}

static void prg_cache_load(void)
{
    char line[LINE_MAX],eacces=0;
    int procfdlen,fd,cmdllen,lnamelen;
    char lname[30],cmdlbuf[512],finbuf[PROGNAME_WIDTH];
    long inode;
    const char *cs,*cmdlp;
    DIR *dirproc=NULL,*dirfd=NULL;
    struct dirent *direproc,*direfd;

    if (prg_cache_loaded ) return;
    prg_cache_loaded=1;
    cmdlbuf[sizeof(cmdlbuf)-1]='\0';
    if (!(dirproc=opendir(PATH_PROC))) goto fail;
    while (errno=0,direproc=readdir(dirproc)) {
#ifdef DIRENT_HAVE_D_TYPE_WORKS
	if (direproc->d_type!=DT_DIR) continue;
#endif
	for (cs=direproc->d_name;*cs;cs++)
	    if (!isdigit(*cs)) 
		break;
	if (*cs) 
	    continue;
	procfdlen=snprintf(line,sizeof(line),PATH_PROC_X_FD,direproc->d_name);
	if (procfdlen<=0 || procfdlen>=sizeof(line)-5) 
	    continue;
	errno=0;
	dirfd=opendir(line);
	if (! dirfd) {
	    if (errno==EACCES) 
		eacces=1;
	    continue;
	}
	line[procfdlen] = '/';
	cmdlp = NULL;
	while ((direfd = readdir(dirfd))) {
#ifdef DIRENT_HAVE_D_TYPE_WORKS
	    if (direfd->d_type!=DT_LNK) 
		continue;
#endif
	    if (procfdlen+1+strlen(direfd->d_name)+1>sizeof(line)) 
		continue;
	    memcpy(line + procfdlen - PATH_FD_SUFFl,PATH_FD_SUFF "/",PATH_FD_SUFFl+1);
	    strcpy(line + procfdlen + 1,direfd->d_name);
	    lnamelen=readlink(line,lname,sizeof(lname)-1);
            lname[lnamelen] = '\0';  /*make it a null-terminated string*/

            extract_type_1_socket_inode(lname,&inode);

            if (inode < 0) extract_type_2_socket_inode(lname,&inode);

            if (inode < 0) continue;

	    if (!cmdlp) {
		if (procfdlen - PATH_FD_SUFFl + PATH_CMDLINEl >= 
		    sizeof(line) - 5) 
		    continue;
		strcpy(line + procfdlen-PATH_FD_SUFFl,PATH_CMDLINE);
		fd = open(line,O_RDONLY);
		if (fd < 0) 
		    continue;
		cmdllen = read(fd,cmdlbuf,sizeof(cmdlbuf) - 1);
		if (close(fd)) 
		    continue;
		if (cmdllen == -1) 
		    continue;
		if (cmdllen < sizeof(cmdlbuf) - 1) 
		    cmdlbuf[cmdllen]='\0';
		if ((cmdlp = strrchr(cmdlbuf,'/'))) 
		    cmdlp++;
		else 
		    cmdlp = cmdlbuf;
	    }

	    snprintf(finbuf,sizeof(finbuf),"%s/%s",direproc->d_name,cmdlp);
	    prg_cache_add(inode,finbuf);
	}
	closedir(dirfd); 
	dirfd = NULL;
    }
    if (dirproc) 
	closedir(dirproc);
    if (dirfd) 
	closedir(dirfd);
    if (!eacces) 
	return;
    if (prg_cache_loaded == 1) {
    fail:
	fprintf(stderr,("(No info Could be read for \"-p\": geteuid()=%d but you should be root.)\n"),geteuid());
    }
    else
	fprintf(stderr,("(Not all processes Could be identified,non-owned process info\n"
			 " will not be shown,you would have to be root to see it all.)\n"));
}


static void ipv4(const char *filename,const char *label) {
    FILE *fp = fopen(filename,"r");
    if (fp == NULL) {
        return;
    }
    char buf[BUFSIZ];
    fgets(buf,BUFSIZ,fp);
    while (fgets(buf,fp)){
        char lip[ADDR_LEN];
        char rip[ADDR_LEN];
        iaddr laddr,raddr;
        unsigned lport,rport,state,txq,rxq,num;
		unsigned tr,tmWhen,ret;
		unsigned uid,timeout,inode;
        int n = sscanf(buf," %d: %x:%x %x:%x %x %x:%x %x:%x %x %x %x %d",&num,&laddr.u,&lport,&raddr.u,&rport,&state,&txq,&rxq,&tr,&tmWhen,&ret,&uid,&timeout,&inode);
        if (n == 14) {
            addr2str(AF_INET,&laddr,lip);
            addr2str(AF_INET,&raddr,rip);

			printf("%10d   %-15s   %5d   %-15s   %6d  %6d  %s   %12s     %5d   %15s\n",lport,lip,rip,label,state2str(state),inode,prg_cache_get(inode));
        }
    }
    fclose(fp);
}

static void ipv6(const char *filename,fp)){
        char lip[ADDR_LEN];
        char rip[ADDR_LEN];
        iaddr6 laddr6,raddr6;
        unsigned lport,num;
     	unsigned tr," %d: %8x%8x%8x%8x:%x %8x%8x%8x%8x:%x %x %x:%x %x:%x %x %x %x %d",&laddr6.u.a,&laddr6.u.b,&laddr6.u.c,&laddr6.u.d,&raddr6.u.a,&raddr6.u.b,&raddr6.u.c,&raddr6.u.d,&inode);
        if (n == 20) {
            addr2str(AF_INET6,&laddr6,lip);	
            addr2str(AF_INET6,&raddr6,rip);
     
			printf("%10d   %-15s   %5d   %-15s   %6d  %6d  %s  %12s     %5d   %15s\n",prg_cache_get(inode));
        }
    }
    fclose(fp);
}


int main(int argc,char *argv[])
{
    prg_cache_load();
	printf("Local Port   Local Address     Fport   Foreign Address   Recv-Q  Send-Q  proto        state     inode   Pid/Program name\n");
    ipv4("/proc/net/tcp","tcp");
    ipv4("/proc/net/udp","udp");
    ipv6("/proc/net/tcp6","tcp6");
    ipv6("/proc/net/udp6","udp6");
	prg_cache_clear();
    return 0;
}


运行结果:

ubuntu下端口关联检测的更多相关文章

  1. html5 http的轮询和Websocket原理

    这篇文章主要介绍了html5 http的轮询和Websocket原理的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. 当iOS应用程序进入后台时,TCP和UDP(与多播)连接会发生什么

    我创建了几个实验:设置1:我创建了一个TCPSender应用程序和一个TCPReceiver应用程序.在本次实验中,我在iOS设备上启动了TCPSender,在另一台iOS设备上启动了TCPReceiver.然后两者都经过验证已建立连接并发送和接收数据.然后我将TCPReceiver应用程序置于后台.TCPSender应用程序指示连接丢失和崩溃(是的,我打算这样).设置2:我创建了一个UDPSen

  3. ios – Swift:使用GCDAsyncUdpSocket接收UDP

    开始:接收:发送:编辑:添加了忘记的代码行.解决方法我终于得到它使用这个套接字设置:

  4. 在iOS中,如何增加主机的HTTP连接限制?

    使用Xcode网络工具,我分析说,我每次只能建立每个主机的4个TCP连接.似乎iOS的每个主机的默认TCP连接限制为4.我们如何增加这个限制?

  5. Swift开发:GCDAsyncSocket通信之TCP服务器

    overridefuncviewDidLoad(){super.viewDidLoad()clientSockets=NSMutableArray()msgTextView.backgroundColor=UIColor.grayColor()msgTextView.text="接收的客户端消息:\n"}//发送消息按钮@IBActionfuncsendBtnClick{ifclientSockets.count==0{return}letmsg=inputTextInput.text!//1.处理请求,

  6. Swift开发:GCDAsyncSocket通信之TCP 客户端

    varmainQueue=dispatch_get_main_queue()overridefuncviewDidLoad(){super.viewDidLoad()}//连接服务器按钮事件@IBActionfuncconBtnClick{do{clientSocket=GCDAsyncSocket()clientSocket.delegate=selfclientSocket.delegateQueue=dispatch_get_global_queue(0,0)tryclientSocket.conn

  7. Swift Socket 实例 两份资料不错

    Swift-使用vaporsocks库进行socket通信(基于TCP、UDP协议)http://www.hangge.com/blog/cache/detail_1588.htmlSwift-使用socket进行通信(附聊天室样例)http://www.hangge.com/blog/cache/detail_756.htmlIBM-Swift/BlueSockethttps://github.

  8. Android从服务器套接字侦听消息

    解决方法您可以在服务中创建一个线程来监听服务器.第二个线程用于发送命令.然后,对于您的服务,您应该创建一个带有处理程序的主线程.此处理程序将处理来自这两个线程的消息.

  9. android – Google Cloud Messaging无法在公司网络上使用4.1.2设备

    我已经实现了一个简单的GCM客户端和服务器.客户端使用currentGCMclientAPIs(而不是deprecatedhelperlibrary).服务器(C#和.NET)遵循相应的serverguidelines(使用HTTP).我的服务器在公司域内的计算机上运行,因此我将客户端设备连接到公司网络内的Wi-Fi接入点,但可以访问Internet.简而言之,我的问题是4.3手机上收到通知,但连

  10. Android BluetoothSocket.isConnected始终返回false

    解决方法我相信jkane001已经解决了他的问题,所以我希望这个答案可以帮助别人.首先在套接字创建之后你应该通过初始连接之后,您将能够使用socket.isConnected()检查连接状态由于connect()方法没有阻塞,所以socket之后可能还没有连接.我建议使用这样的东西顺便说一句,我发现在一些Android设备上isConnected()总是返回false.在这种情况下,只是尝试写一些东西到socket并检查是否没有异常.

随机推荐

  1. crontab发送一个月份的电子邮件

    ubuntu14.04邮件服务器:Postfixroot收到来自crontab的十几封电子邮件.这些邮件包含PHP警告.>我已经解决了这些警告的原因.>我已修复每个cronjobs不发送电子邮件(输出发送到>/dev/null2>&1)>我删除了之前的所有电子邮件/var/mail/root/var/spool/mail/root但我仍然每小时收到十几封电子邮件.这些电子邮件来自cronjobs,

  2. 模拟两个ubuntu服务器计算机之间的慢速连接

    我想模拟以下场景:假设我有4台ubuntu服务器机器A,B,C和D.我想在机器A和机器C之间减少20%的网络带宽,在A和B之间减少10%.使用网络模拟/限制工具来做到这一点?

  3. ubuntu-12.04 – 如何在ubuntu 12.04中卸载从源安装的redis?

    我从源代码在Ubuntu12.04上安装了redis-server.但在某些时候它无法完全安装,最后一次makeinstallcmd失败.然后我刚刚通过apt包安装.现在我很困惑哪个安装正在运行哪个conf文件?实际上我想卸载/删除通过源安装的所有内容,只是想安装一个包.转到源代码树并尝试以下命令:如果这不起作用,您可以列出软件自行安装所需的步骤:

  4. ubuntu – “apt-get source”无法找到包但“apt-get install”和“apt-get cache”可以找到它

    我正在尝试下载软件包的源代码,但是当我运行时它无法找到.但是当我运行apt-cache搜索squid3时,它会找到它.它也适用于apt-getinstallsquid3.我使用的是Ubuntu11.04服务器,这是我的/etc/apt/sources.list我已经多次更新了.我尝试了很多不同的debs,并没有发现任何其他地方的错误.这里的问题是你的二进制包(deb)与你的源包(deb-src)不

  5. ubuntu – 有没有办法检测nginx何时完成正常关闭?

    &&touchrestarted),因为即使Nginx没有完成其关闭,touch命令也会立即执行.有没有好办法呢?这样的事情怎么样?因此,pgrep将查找任何Nginx进程,而while循环将让它坐在那里直到它们全部消失.你可以改变一些有用的东西,比如睡1;/etc/init.d/Nginx停止,以便它会休眠一秒钟,然后尝试使用init.d脚本停止Nginx.你也可以在某处放置一个计数器,这样你就可以在需要太长时间时发出轰击信号.

  6. ubuntu – 如何将所有外发电子邮件从postfix重定向到单个地址进行测试

    我正在为基于Web的应用程序设置测试服务器,该应用程序发送一些电子邮件通知.有时候测试是使用真实的客户数据进行的,因此我需要保证服务器在我们测试时无法向真实客户发送电子邮件.我想要的是配置postfix,以便它接收任何外发电子邮件并将其重定向到一个电子邮件地址,而不是传递到真正的目的地.我正在运行ubuntu服务器9.10.先感谢您设置本地用户以接收所有被困邮件:你需要在main.cf中添加:然后

  7. ubuntu – vagrant无法连接到虚拟框

    当我使用基本的Vagrantfile,只配置了两条线:我看到我的虚拟框打开,但是我的流氓日志多次显示此行直到超时:然后,超时后的一段时间,虚拟框框终于要求我登录,但是太久了!所以我用流氓/流氓记录.然后在我的物理机器上,如果我“流氓ssh”.没有事情发生,直到:怎么了?

  8. ubuntu – Nginx – 转发HTTP AUTH – 用户?

    我和Nginx和Jenkins有些麻烦.我尝试使用Nginx作为Jenkins实例的反向代理,使用HTTP基本身份验证.它到目前为止工作,但我不知道如何传递带有AUTH用户名的标头?}尝试将此指令添加到您的位置块

  9. Debian / Ubuntu – 删除后如何恢复/ var / cache / apt结构?

    我在ubuntu服务器上的空间不足,所以我做了这个命令以节省空间但是现在在尝试使用apt时,我会收到以下错误:等等显然我删除了一些目录结构.有没有办法做apt-getrebuild-var-tree或类似的?

  10. 检查ubuntu上安装的rubygems版本?

    如何查看我的ubuntu盒子上安装的rubygems版本?只是一个想法,列出已安装的软件包和grep为ruby或宝石或其他:)dpkg–get-selections

返回
顶部