欢迎来到个人简历网!永久域名:gerenjianli.cn (个人简历全拼+cn)
当前位置:首页 > 范文大全 > 实用文>Linux系统进程深入理解

Linux系统进程深入理解

2024-05-01 08:16:23 收藏本文 下载本文

“lovejsko”通过精心收集,向本站投稿了5篇Linux系统进程深入理解,下面是小编帮大家整理后的Linux系统进程深入理解,希望对大家的学习与工作有所帮助。

Linux系统进程深入理解

篇1:Linux系统进程深入理解

1. 什么是进程

进程是处于执行期的程序以及它所包含的所有资源的总称,包括虚拟处理器,虚拟空间,寄存器,堆栈,全局数据段等,

在Linux中,每个进程在创建时都会被分配一个数据结构,称为进程控制块(Process Control Block,简称PCB)。PCB中包含了很多重要的信息,供系统调度和进程本身执行使用。所有进程的PCB都存放在内核空间中。PCB中最重要的信息就是进程PID,内核通过这个PID来唯一标识一个进程。PID可以循环使用,最大值是32768。init进程的pid为1,其他进程都是init进程的后代。

除了进程控制块(PCB)以外,每个进程都有独立的内核堆栈(8k),一个进程描述符结构,这些数据都作为进程的控制信息储存在内核空间中;而进程的用户空间主要存储代码和数据。

2.进程的创建

进程是通过调用::fork,::vfork()和::clone()系统调用创建新进程。在内核中,它们都是调用do_fork实现的。传统的fork函数直接把父进程的所有资源复制给子进程。而Linux的::fork()使用写时拷贝页实现,也就是说,父进程和子进程共享同一个资源拷贝,只有当数据发生改变时,数据才会发生复制。通常的情况,子进程创建后会立即调用exec(),这样就避免复制父进程的全部资源。

三者的区别如下:

::fork():父进程的所有数据结构都会复制一份给子进程(写时拷贝页)。

::vfork():只复制task_struct和内核堆栈,所以生成的只是父进程的一个线程(无独立的用户空间)。

::clone():功能强大,带了许多参数。::clone()可以让你有选择性的继承父进程的资源,既可以选择像::vfork()一样和父进程共享一个虚拟空间,从而使创造的是线程,你也可以不和父进程共享,你甚至可以选择创造出来的进程和父进程不再是父子关系,而是兄弟关系,

3. 进程的撤销

进程通过调用exit()退出执行,这个函数会终结进程并释放所有的资源。父进程可以通过wait4()查询子进程是否终结。进程退出执行后处于僵死状态,直到它的父进程调用wait()或者waitpid()为止。父进程退出时,内核会指定线程组的其他进程或者init进程作为其子进程的新父进程。当进程接收到一个不能处理或忽视的信号时,或当在内核态产生一个不可恢复的CPU异常而内核此时正代表该进程在运行,内核可以强迫进程终止。

4. 进程管理

内核把进程信息存放在叫做任务队列(task list)的双向循环链表中(内核空间)。链表中的每一项都是类型为task_struct,称为进程描述符结构(process descriptor),包含了一个具体进程的所有信息,包括打开的文件,进程的地址空间,挂起的信号,进程的状态等。

Linux通过slab分配器分配task_struct,这样能达到对象复用和缓存着色(通过预先分配和重复使用task_struct,可以避免动态分配和释放所带来的资源消耗)。    内核把所有处于TASK_RUNNING状态的进程组织成一个可运行双向循环队列。调度函数通过扫描整个可运行队列,取得最值得执行的进程投入执行。避免扫描所有进程,提高调度效率。

5. 进程的内核堆栈

Linux为每个进程分配一个8KB大小的内存区域,用于存放该进程两个不同的数据结构:thread_info和进程的内核堆栈。

进程处于内核态时使用不同于用户态堆栈,内核控制路径所用的堆栈很少,因此对栈和描述符来说,8KB足够了。

篇2:linux进程管理之wait系统调用

六: wait4 ()系统调用

在父进程中,用wait4()可以获得子进程的退出状态,并且防止在父进程退出前,子进程退出造成僵死 状态,这是我们这节分析的最后一个小节了。

关于wait4()在用户空间的调用方式可以自行参考相关资料,在这里只是讨论内核对这个系统调用的实 现过程。

Wait4()的系统调用入口为sys_wait4().代码如下所示:

asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, int options, struct rusage __user *ru){ long ret; //options的标志为须为WNOHANG…__WALL的组合,否则会出错 //相关标志的作用在do_wait()中再进行分析 if (options & ~(WNOHANG|WUNTRACED|WCONTINUED| __WNOTHREAD|__WCLONE|__WALL)) return -EINVAL; ret = do_wait(pid, options | WEXITED, NULL, stat_addr, ru); /* avoid REGPARM breakage on x86: */ prevent_tail_call(ret); return ret;}

do_wait()是其中的核心处理函数。代码如下:

static long do_wait(pid_t pid, int options, struct siginfo __user *infop, int __user *stat_addr, struct rusage __user *ru){ //初始化一个等待队列 DECLARE_WAITQUEUE(wait, current); struct task_struct *tsk; int flag, retval; int allowed, denied; //将当前进程加入等待队列,子进程退出给父进程发送信号会wake up些等待队列 add_wait_queue(¤t->signal->wait_chldexit,&wait);repeat: flag = 0; allowed = denied = 0; //设置进程状态为TASK_INTERRUPTIBLE.下次调度必须要等到子进程唤醒才可以了 current->state = TASK_INTERRUPTIBLE; read_lock(&tasklist_lock); tsk = current; do { struct task_struct *p; struct list_head *_p; int ret; //遍历进程下的子进程 list_for_each(_p,&tsk->children) { p = list_entry(_p, struct task_struct, sibling); //判断是否是我们要wait 的子进程 ret = eligible_child(pid, options, p); if (!ret) continue; if (unlikely(ret < 0)) { denied = ret; continue; } allowed = 1; switch (p->state) { //子进程为TASK_TRACED.即处于跟踪状态。则取子进程的相关信息 case TASK_TRACED: flag = 1; //判断是否是被父进程跟踪的子进程 //如果是则返回1..不是返回0 if (!my_ptrace_child(p))continue; /*FALLTHROUGH*/ case TASK_STOPPED: flag = 1; //WUNTRACED:子进程是停止的,也马上返回 //没有定义WUNTRACED 参数.继续遍历子进程 /*从此看出.生父进程是不会处理STOP状态的子进程的.只有发起跟踪的进程才会 */ if (!(options & WUNTRACED) &&!my_ptrace_child(p))continue; //WNOWAIT:不会将zombie子进程的退出状态撤销 //下次调用wait系列函数的时候还可以继续获得这个退出状态 retval = wait_task_stopped(p, ret == 2, (options & WNOWAIT), infop, stat_addr, ru); if (retval == -EAGAIN)goto repeat; if (retval != 0) /* He released the lock. */goto end; break; default: // case EXIT_DEAD: //不需要处理DEAD状态 if (p->exit_state == EXIT_DEAD)continue; // case EXIT_ZOMBIE: //子进程为僵尸状态 if (p->exit_state == EXIT_ZOMBIE) {if (ret == 2) goto check_continued;if (!likely(options & WEXITED))continue;retval = wait_task_zombie( p, (options & WNOWAIT), infop, stat_addr, ru);/* He released the lock. */if (retval != 0) goto end;break; }check_continued: /* * It's running now, so it might later * exit, stop, or stop and then continue. */ flag = 1; //WCONTINUED:报告任何继续运行的指定进程号的子进程的状态 if (!unlikely(options & WCONTINUED))continue; //取进程的相关状态 retval = wait_task_continued(p, (options & WNOWAIT),infop, stat_addr, ru); if (retval != 0) /* He released the lock. */goto end; break; } } //遍历被跟踪出去的子进程 //从这里可以看出.如果一个子进程被跟踪出去了.那么子进程的退出 //操作并不是由生父进程进行了 if (!flag) { list_for_each(_p, &tsk->ptrace_children) { p = list_entry(_p, struct task_struct, ptrace_list); if (!eligible_child(pid, options, p))continue; flag = 1; break; } } if (options & __WNOTHREAD) break; //也有可能是进程中的线程在wait其fork出来的子进程 tsk = next_thread(tsk); BUG_ON(tsk->signal != current->signal); } while (tsk != current); // read_unlock(&tasklist_lock); if (flag) { retval = 0; //如果定义了WHNOHANG:马上退出 if (options & WNOHANG) goto end; retval = -ERESTARTSYS; if (signal_pending(current)) goto end; schedule(); goto repeat; } retval = -ECHILD; if (unlikely(denied) && !allowed) retval = denied;end: //将进程设为运行状态,从等待队列中移除 current->state = TASK_RUNNING; remove_wait_queue(¤t->signal->wait_chldexit,&wait); if (infop) { if (retval >0) retval = 0; else { /* * For a WNOHANG return, clear out all the fields * we would set so the user can easily tell the * difference. */ if (!retval) retval = put_user(0, &infop->si_signo); if (!retval) retval = put_user(0, &infop->si_errno); if (!retval) retval = put_user(0, &infop->si_code); if (!retval) retval = put_user(0, &infop->si_pid); if (!retval) retval = put_user(0, &infop->si_uid); if (!retval) retval = put_user(0, &infop->si_status); } } return retval;}

这代段码还是比较简单。先遍历进程的子进程,再遍历被跟踪出去的进程,再遍历线程中的线程。我 们分析一下里面用到的几个重要的子函数。

eligible_child用来判断子进程是否是我们想要wait的子进程.代码如下:

static int eligible_child(pid_t pid, int options, struct task_struct *p){ int err; //根据PID判断是不是我们要wait的子进程 //pid >0:等待的子程程的进程号等于pid //pid = 0:等待进程组号等于当前进程组号的所有子进程 //pid < -1 :等待任何进程组号等于pid绝对值的子进程 //pid == -1 :等待任何子进程 if (pid >0) {if (p->pid != pid) return 0; } else if (!pid) { if (process_group(p) != process_group(current)) return 0; } else if (pid != -1) { if (process_group(p) != -pid) return 0; } //如果子进程exit_signal ==-1且没有被跟踪.那不会对子进程进行回收 if (p->exit_signal == -1 && !p->ptrace) return 0; if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0)) && !(options & __WALL)) return 0; /* * Do not consider thread group leaders that are * in a non-empty thread group: */ //如果子进程是进程组leader,且进程组不为空 if (delay_group_leader(p)) return 2; err = security_task_wait(p); if (err) return err; return 1;}

对TASK_TRACED和TASK_STOPPED状态的子进程操作是在wait_task_stopped()中完成的。它的代码如下:

static int wait_task_stopped(struct task_struct *p, int delayed_group_leader, int noreap, struct siginfo __user *infop, int __user *stat_addr, struct rusage __user *ru){ int retval, exit_code; //进程退出状态码为零.没有相关退出信息 if (!p->exit_code) return 0; // if (delayed_group_leader && !(p->ptrace & PT_PTRACED) && p->signal && p->signal->group_stop_count >0) return 0; //正在取task里面的信息,为了防止意外释放,先增加它的引用计数 get_task_struct(p); read_unlock(&tasklist_lock); //如果WNOWAIT 被定义 if (unlikely(noreap)) { pid_t pid = p->pid; uid_t uid = p->uid; int why = (p->ptrace & PT_PTRACED) ? CLD_TRAPPED : CLD_STOPPED; exit_code = p->exit_code; //退出状态码为零,但是过程已经处于退出状态中(僵尸或者是死进程) if (unlikely(!exit_code) || unlikely(p->exit_state)) goto bail_ref; //把子进程的各项信息保存起来 //返回值是退出子进程的PID return wait_noreap_copyout(p, pid, uid, why, exit_code, infop, ru); } write_lock_irq(&tasklist_lock); //如果子进程没有退出.只要取子进程的退出信息,再清除子进程的退出信息 //即可 exit_code = xchg(&p->exit_code, 0); if (unlikely(p->exit_state)) { p->exit_code = exit_code; exit_code = 0; } if (unlikely(exit_code == 0)) {write_unlock_irq(&tasklist_lock);bail_ref: put_task_struct(p); return -EAGAIN; } //将子进程加到父进程子链表的末尾 remove_parent(p); add_parent(p); write_unlock_irq(&tasklist_lock); //收集相关的信息 retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; if (!retval && stat_addr) retval = put_user((exit_code << 8) | 0x7f, stat_addr); if (!retval && infop) retval = put_user(SIGCHLD, &infop->si_signo); if (!retval && infop) retval = put_user(0, &infop->si_errno); if (!retval && infop) retval = put_user((short)((p->ptrace & PT_PTRACED) ? CLD_TRAPPED : CLD_STOPPED), &infop->si_code); if (!retval && infop) retval = put_user(exit_code, &infop->si_status); if (!retval && infop) retval = put_user(p->pid, &infop->si_pid); if (!retval && infop) retval = put_user(p->uid, &infop->si_uid); if (!retval) retval = p->pid; //减少task的引用计数 put_task_struct(p); BUG_ON(!retval); return retval;}

对僵尸进程的操作是由wait_task_zombie()完成的,

代如如下:

static int wait_task_zombie(struct task_struct *p, int noreap, struct siginfo __user *infop, int __user *stat_addr, struct rusage __user *ru){ unsigned long state; int retval; int status; //WNOWAIT被设置.不需要释放子进程的资源,只要取相关信息即可 if (unlikely(noreap)) { pid_t pid = p->pid; uid_t uid = p->uid; int exit_code = p->exit_code; int why, status; //子进程不为EXIT_ZOMBIE .异常退出 if (unlikely(p->exit_state != EXIT_ZOMBIE)) return 0; //没有退出信号具没有被跟踪.退出 if (unlikely(p->exit_signal == -1 && p->ptrace == 0)) return 0; //增加引用计数 get_task_struct(p); read_unlock(&tasklist_lock); if ((exit_code & 0x7f) == 0) { why = CLD_EXITED; status = exit_code >>8; } else { why = (exit_code & 0x80) ? CLD_DUMPED : CLD_KILLED; status = exit_code & 0x7f; }//取相关信息 return wait_noreap_copyout(p, pid, uid, why, status, infop, ru); } /* * Try to move the task's state to DEAD * only one thread is allowed to do this: */ //将子进程状态设为EXIT_DEAD状态 state = xchg(&p->exit_state, EXIT_DEAD); //如果子进程不为EXIT_ZOMBIE状态,异常退出 if (state != EXIT_ZOMBIE) { BUG_ON(state != EXIT_DEAD); return 0; } //没有退出信号,且没有被跟踪 if (unlikely(p->exit_signal == -1 && p->ptrace == 0)) {return 0; } //子进程的real_parent等于当前父进程.说明子进程并没有被跟踪出去 if (likely(p->real_parent == p->parent) && likely(p->signal)) { struct signal_struct *psig; struct signal_struct *sig; //更新父进程的一些统计信息 spin_lock_irq(&p->parent->sighand->siglock); psig = p->parent->signal; sig = p->signal; psig->cutime = cputime_add(psig->cutime, cputime_add(p->utime, cputime_add(sig->utime,sig->cutime))); psig->cstime = cputime_add(psig->cstime, cputime_add(p->stime, cputime_add(sig->stime,sig->cstime))); psig->cmin_flt += p->min_flt + sig->min_flt + sig->cmin_flt; psig->cmaj_flt += p->maj_flt + sig->maj_flt + sig->cmaj_flt; psig->cnvcsw += p->nvcsw + sig->nvcsw + sig->cnvcsw; psig->cnivcsw += p->nivcsw + sig->nivcsw + sig->cnivcsw; psig->cinblock += task_io_get_inblock(p) + sig->inblock + sig->cinblock; psig->coublock += task_io_get_oublock(p) + sig->oublock + sig->coublock; spin_unlock_irq(&p->parent->sighand->siglock); } /* * Now we are sure this task is interesting, and no other * thread can reap it because we set its state to EXIT_DEAD. */ //取得相关的退出信息 read_unlock(&tasklist_lock); retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; status = (p->signal->flags & SIGNAL_GROUP_EXIT) ? p->signal->group_exit_code : p->exit_code; if (!retval && stat_addr) retval = put_user(status, stat_addr); if (!retval && infop) retval = put_user(SIGCHLD, &infop->si_signo); if (!retval && infop) retval = put_user(0, &infop->si_errno); if (!retval && infop) { int why; if ((status & 0x7f) == 0) { why = CLD_EXITED; status >>= 8; } else { why = (status & 0x80) ? CLD_DUMPED : CLD_KILLED; status &= 0x7f; } retval = put_user((short)why, &infop->si_code); if (!retval) retval = put_user(status, &infop->si_status); } if (!retval && infop) retval = put_user(p->pid, &infop->si_pid); if (!retval && infop) retval = put_user(p->uid, &infop->si_uid); if (retval) { // TODO: is this safe? p->exit_state = EXIT_ZOMBIE; return retval; } retval = p->pid; //当前进程不是生父进程.则说明进程是被跟踪出去了 // TODO:子进程exit退出的时候,只会向其当前父进程发送信号的哦^_^ if (p->real_parent != p->parent) {write_lock_irq(&tasklist_lock); /* Double-check with lock held. */ if (p->real_parent != p->parent) { //将进程从跟踪链表中脱落,并设置父进程为生父进程 __ptrace_unlink(p); // TODO: is this safe? //重新设置为EXIT_ZOMBI状态 p->exit_state = EXIT_ZOMBIE; /* * If this is not a detached task, notify the parent. * If it's still not detached after that, don't release * it now. */ //如果允许发送信息,则给生父进程发送相关信号 if (p->exit_signal != -1) { do_notify_parent(p, p->exit_signal); if (p->exit_signal != -1)p = NULL;} } write_unlock_irq(&tasklist_lock); } //释放子进程的剩余资源 if (p != NULL) release_task(p); BUG_ON(!retval); return retval;}

至此,我们看到了继子进程退出之后的完整处理。在此,值得注意的是。子进程在退出的时候会给父 进程发送相应的信号(例如SIG_CHILD),默认的信号处理函数也会进行相应的处理。

七:等待队列的操作

在这里,我们第一次接触到了等待队列,我们就以上面的代码做为例子来分析一下。

1:申请一个等待队列:

DECLARE_WAITQUEUE()://name:等待队列的名字。Tsk:所要操作的task#define DECLARE_WAITQUEUE(name, tsk) \ wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)#define __WAITQUEUE_INITIALIZER(name, tsk) { \ .private = tsk, \ .func = default_wake_function, \ .task_list = { NULL, NULL } }

default_wake_function()为默认的唤醒处理函数。

2:添加等待队列。

在上面的代码中,有:

add_wait_queue(¤t->signal->wait_chldexit,&wait);

它的意思是将wait添加至¤t->signal->wait_chldexit中。代码如下:

void fastcall add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait){ unsigned long flags; wait->flags &= ~WQ_FLAG_EXCLUSIVE; //为了防止竞争。加锁 spin_lock_irqsave(&q->lock, flags); //添加至队列 __add_wait_queue(q, wait); //解锁 spin_unlock_irqrestore(&q->lock, flags);}

3:唤醒操作:

在do_notify_parent()中有这样的代码片段:

……__wake_up_parent(tsk, tsk->parent);……__wake_up_parent()的代码如下:static inline void __wake_up_parent(struct task_struct *p,struct task_struct *parent){ wake_up_interruptible_sync(&parent->signal->wait_chldexit);}

parent->signal->wait_chldexit这个队列很熟吧?我们在父进程中添加的等待队列就是添加在 这里哦。^_^

唤醒队列的操作是由wake_up_interruptible_sync()完成的,代码如下:

wake_up_interruptible_sync() à __wake_up_sync()à__wake_up_common():static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int sync, void *key){ struct list_head *tmp, *next; list_for_each_safe(tmp, next, &q->task_list) { wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list); unsigned flags = curr->flags; if (curr->func(curr, mode, sync, key) && (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive) break; }}

上述操作会遍历整个等待队列,然后运行对应的函数。我们在前面申请等待队列的时候,默认的函数 为:default_wake_function()。它会将操作的task放入运行队列,并将状态设为RUNING这个函数等之 后我们分析进程切换与调度的时候再来分析。

八:小结

通过分析进程的创建,执行与消息等过程,可以对子程管理子系统有一个大概的了解。该子系统与其 它子系统关系十分密切。对进程资源的管理和释放是理解这个子系统的难点。在下一个小节点,我们接着 分析进程的切换与调度。

篇3:linux系统快速查看进程pid的方法

一个很简单的命令,pgrep,可以迅速定位包含某个关键字的进程的pid;使用这个命令,再也不用ps aux 以后去对哪个进程的pid了

用法:

pgrep -l XXX

说明:

-l参数,可以显示出pid及进程名字;不加-l只显示pid,谁知道是什么进程的pid

举例:

# pgrep httpd

2092

2094

2096

2098

2106

2108

2109

2111

14705

# pgrep -l httpd

2092 httpd

2094 httpd

2096 httpd

2098 httpd

2106 httpd

2108 httpd

2109 httpd

2111 httpd

14705 httpd

当然,pgrep的用法不仅仅如此,有兴趣的同学可以研究;不过就本人来说,应用范围有限,本着应用之上的原则,未对pgrep做太多的学习,

linux系统快速查看进程pid的方法

篇4:linux系统进程管理之dstat的使用

dstat一款多功能系统资源监视工具,支持的功能非常多例如:cpu、内存、负载、文件锁、socket套接字、网络、进程、分页文件、文件系统等等的众多内容都可以逐一显示,

dstat下载地址:pkgs.repoforge.org/dstat/ 如果centos中没有安装则可以直接使用yum安装,如果不想使用yum安装可以去上面的站点下载。

这是dstat的打开界面,它会一直刷新系统状态并且将这些内容返回到屏幕当中,如果直接输入dstat,程序则会提示“你没有做出任何筛选状态,将使用-cdngy来作为默认选项”接下来介绍一下这些选项。

常用选项:

-c:显示cpu使用情况

-d:显示磁盘使用情况

-n:显示网络IO

-g:显示分页文件

-y:系统相关数据

-m:内存相关数据

-p:显示进程

-s:交换空间相关信息

--fs:文件系统相关数据

-r:总计io

--lock:文件锁

--socket:套接字文件

--top-cpu:显示最占用cpu的进程

--top-bio:显示最占用块设备io的进程

--top-mem:显示最消耗内存的进程

--top-io:显示最占用io的进程

............

当然还有更多选项供用户选择,可直接使用-h或者--help或者man手册页获取帮助信息

如果我们需要让程序输出一定内容后自动停止下来则可以输入“dstat 1 3”最后程序将于第四次显示后自动退出(这些数字可以用户自定义的,

当我们给过多参数时dstat则判断这个终端是否可以显示完整,如果显示不完整则按照标准输出来显示。

我这里给了-cdngymp(显示了cpu、磁盘、网络、分页文件、系统信息、内存、以及进程等)七个选项执行后程序返回第一行的内容提示终端宽度太小。这时需要结束程序将终端放大后使用。

来看下它自动退出吧。前面有说使用dstat 1 3意思是在第一行显示完成后随后三行刷新一遍后退出

如果把数字1改为2那么就代表了从第二行开始的每一行起刷新两次后再返回给用户,这个请各位自己尝试下吧没办法演示(我也想做gif图。。。可是我用的ubuntu),剩下就是多次练习就好了,就写到这里吧。

篇5:linux系统中Nginx守护进程(自动启动nginx)linux操作系统

守护进程其实就是一个监控功能了,我们可以利用监控功能来监控一指定应用有没有启动了,如果没有启动我们就把它启动了,下面来看一个Nginx守护进程的操作方法,

最近VPS的Nginx不知道为啥,会无缘无故关掉。可能是负载过高被母鸡Kill了。但是为了保持网站在线,写了个守护进程:

代码如下复制代码

aa=`pgrep -f nginx | wc -l`

if [ “$aa” = 0 ]

then

/usr/local/nginx/sbin/nginx

/usr/local/php/sbin/php-fpm start

else

echo “the program is running”

fi

把以上脚本写成一个.sh文件。然后用Crontab设置自动执行,发现Nginx不在进程中,自动启动Nginx和PHP-FPM。否则输出The Program is Running.

上面是一个针对Linux环境下的Nginx守护进程,现在来个增强版的.同学们看着改来用吧.

代码如下复制代码

ipv4=`ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d “addr:”`

#把xxx@163.com改成自己的邮箱

EMAIL_TO=xxx@163.com

#可以把nginx改为其他要守护的进程名字

nd=`pgrep -f nginx | wc -l`

if [ “$nd” = 0 ]

then

echo -e “Server IP is : $ipv4 ” | mail -s “The nginx program is Dead” $EMAIL_TO

/usr/local/nginx/sbin/nginx #当被守护进程不存在后,自动启动的进程,

可修改

/usr/local/php/sbin/php-fpm start #当被守护进程不存在后,自动启动的进程。可修改

else

echo “the program is running”

fi

mail命令需要mailx这个程序,用下面这条命令安装。

代码如下复制代码

yum -y install mailx

跟上个版本一样把以上脚本写成一个.sh文件。然后用Crontab设置自动执行,这个版本是增强了邮件通知功能,发现Nginx不在进程中,自动启动Nginx和PHP-FPM并通过邮件通知管理检查。否则输出The Program is Running.

这样还会有一封邮件发送给你哦,哈哈是不是更智能了呀,比起windows系统是要智能了许多了哦。

【Linux系统进程深入理解】相关文章:

1.看到一个进程完整的命令行Unix系统

2.进程的近义词

3.wininit wininit.exe 进程信息

4.跨进程API Hook.net

5.a.exe的进程信息

6.中国各地区市场化进程报告

7.理解_

8.新课改进程中我的语文课堂

9.商洛市生态园林城市生态化进程评价

10.我国大客机研制及产业进程

下载word文档
《Linux系统进程深入理解.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度: 评级1星 评级2星 评级3星 评级4星 评级5星
点击下载文档

文档为doc格式

  • 返回顶部