文档章节

深入理解子进程/守护进程/进程高可用实现

乐搏学院
 乐搏学院
发布于 2017/02/27 11:13
字数 1289
阅读 5
收藏 0

单个进程:

说明: 进程是程序执行的实例,运行过程中,内核会将程序代码载入内存,为程序变量分配内存建立数据结构,记录进程相关信息,可以将其理解为容器,容器内的资源可以动态调整,但容器内的程序只能使用容器内的资源.

 

生成进程:

说明: 类Unix系统提供fork()系统调用,它非常特殊,普通函数调用1次返回1次,但它调用1次返回2次,因为操作系统自动把当前进程(父进程)复制出一份(子进程),然后在父进程和子进程内返回,子进程永远返回0,父进程返回子进程的pid,这样一个父进程可以fork多个子进程,父进程要记下每个子进程的pid,而子进程只需要os.getppid()就可以拿到父进程的pid

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import os

# 说明: 导入其它模块

if __name__ == '__main__':

    print 'master process pid(%s) start ...' % (os.getpid())

    pid = os.fork()

    if pid == 0:

        print 'I am a sub process (%s) created by %s.' % (os.getpid(), os.getppid())

    else:

        print 'I (%s) created a sub process (%s)' % (os.getpid(), pid)

说明: 由于os.fork()会返回2次,分别在子进程内返回然后在主进程内返回,所以如上代码if语句的两个判断都会被打印,第一次返回主进程创建了子进程,第二次进入子进程返回被主进程创建.

 

守护进程:

1. 守护进程也称后台进程,要实现后台进程必须使其与其与原运行环境隔离,包括未关闭的文件描述符,控制终端,会话,进程组,工作目录,以及文件创建掩码等等,有时还必须保证单实例运行

wKiom1gAS-myOEioAABNhnMRFWM123.png

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import os

import sys

import time

import atexit

from signal import SIGTERM

# 说明: 导入其它模块

class Daemon(object):

    def __init__(self, pidfile='daemon.pid', stdin=os.devnull,

                 stdout='daemon.log', stderr='daemon.log'):

        self.stdin = stdin

        self.stdout = stdout

        self.stderr = stderr

        self.pidfile = pidfile

    def daemonize(self):

        sys.stdout.write('current process => %s, leader process => %s%s' %

                         (os.getpid(), os.getsid(), os.linesep))

        try:

            pid = os.fork()

            if pid != 0:

                sys.exit(0)

        except OSError, e:

            sys.exit(1)

        os.chdir('.')

        os.umask(0)

        os.setsid()

        sys.stdout.write('current process => %s, leader process => %s%s' %

                         (os.getpid(), os.getsid(), os.linesep))

        try:

            pid = os.fork()

            if pid != 0:

                sys.exit(0)

        except OSError, e:

            sys.exit(1)

        sys.stdout.write('current process => %s, leader process => %s' %

                         (os.getpid(), os.getsid(), os.linesep))

        sys.stdout.flush()

        sys.stderr.flush()

        si = file(self.stdin, 'r')

        so = file(self.stdout, 'a+')

        se = file(self.stderr, 'a+')

        os.dup2(si.fileno(), sys.stdin.fileno())

        os.dup2(so.fileno(), sys.stdout.fileno())

        os.dup2(se.fileno(), sys.stderr.fileno())

        atexit.register(self.delpid)

        strpid = ''.join([str(os.getpid()), os.linesep])

        file(self.pidfile, 'w+b').write(strpid)

    def delpid(self):

        os.remove(self.pidfile)

    def start(self):

        try:

            with open(self.pidfile, 'r+b') as f:

                pid = int(f.read().strip())

        except IOError, e:

            pid = None

        if pid:

            msg = 'pidfile %s already exist. Daemon already running?%s'

            sys.stdout.write(msg % (self.pidfile, os.linesep))

            sys.exit(1)

        self.daemonize()

        self.run()

    def stop(self):

        try:

            with open(self.pidfile, 'r+b') as f:

                pid = int(f.read().strip())

        except IOError, e:

            pid = None

        if not pid:

            msg = 'pidfile %s does not exist. Daemon not running?%s'

            sys.stdout.write(msg % (self.pidfile, os.linesep))

            sys.exit(1)

        try:

            while True:

                os.kill(pid, SIGTERM)

                time.sleep(0.1)

        except OSError, e:

            if os.path.exists(self.pidfile):

                self.delpid()

            sys.exit(1)

    def restart(self):

        self.stop()

        self.start()

    def run(self):

        pass

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import os

import time

from daemon import Daemon

# 说明: 导入其它模块

class TaskRun(Daemon):

    def __init__(self*args, **kwargs):

        super(TaskRun, self).__init__(*args, **kwargs)

    def run(self):

        with open('running.log''a+b')

            while True:

                timestamp = str(time.time())

                f.write(''.join([timestamp, os.linesep]))

                f.flush()

                time.sleep(1)

if __name__ == '__main__':

    = TaskRun()

    t.start()

 

进程管控:

说明: 在运维开发中很多时候程序BUG导致程序异常退出,crond时间精度上不可控,常常导致一段时间服务不可用,为了增强程序的可用性,可让子进程处理业务,主进程接收子进程SIGCHLD信号,此信号为系统默认信号子进程退出时会主动发送给主进程,主进程只需要捕捉此信号并启动新的子进程接管业务即可实现业务的高可用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

#!/usr/bin/env python

# -*- coding: utf-8 -*-

"""

#

# Authors: limanman

# OsChina: http://xmdevops.blog.51cto.com/

# Purpose:

#

"""

# 说明: 导入公共模块

import time

import signal

import multiprocessing

# 说明: 导入其它模块

def task(interval):

    for in xrange(5):

        print _

        time.sleep(interval)

    print 'found notice: sub process(%s) exit with error!' % (multiprocessing.current_process())

def signal_handler(sig_num, frame):

    = multiprocessing.Process(target=task, args=(1,))

    p.daemon = True

    p.start()

if __name__ == '__main__':

    = multiprocessing.Process(target=task, args=(1,))

    p.daemon = True

    p.start()

    = signal.signal(signal.SIGCHLD, signal_handler)

    while True:

        signal.pause()

 

 

登录乐搏学院官网http://www.learnbo.com/

或关注我们的官方微博微信,还有更多惊喜哦~

 

本文出自 “满满李 - 运维开发之路” 博客,请务必保留此出处http://xmdevops.blog.51cto.com/11144840/1861815

© 著作权归作者所有

共有 人打赏支持
乐搏学院
粉丝 6
博文 526
码字总数 707467
作品 0
丰台
程序员
从进程组、会话、终端的概念深入理解守护进程

从进程组、会话、终端的概念深入理解守护进程 一、写在前面 「守护进程」是 Linux 的一种长期运行的后台服务进程,也有人称它为「精灵进程」。我们常见的 httpd、named、sshd 等服务都是以守...

肖邦0526
04/29
0
0
【原创】服务器开发之 Daemon 和 Keepalive

由于业务开发需要,需要对数据库代理进行研究,在研究 MySQL Proxy 实现原理的过程中,对一些功能点进行了分析总结。本文主要讲解下 MySQL Proxy 的 daemon 和 keepalive 功能实现原理。 My...

摩云飞
2013/03/24
0
5
fork函数替换为SylixOS进程技术笔记

1、使用范围 SylixOS是一款为嵌入式系统设计的硬实时系统。为了保证系统的实时性,系统创建子进程时不做页表切换(页表切换很耗时间,不利于实时性的体现),即父子进程共享同一个页表,而对...

张荣荣123
2017/02/06
0
0
Java 多线程回顾

做java web开发,一直以来比较依赖java框架和oracle数据库的功能。因为一般遇到高并发的情况并不多,企业内软件多半用户数不多,即使偶尔遇到,也都在oracle数据库中处理了。 对java的多线程...

五大三粗
2015/11/25
9
0
守护进程daemon详解

一:守护进程概述 Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,...

随性_
2016/07/15
148
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

人生苦短:Python里的17个“超赞操作

人生苦短,我选Python”。那么,你真的掌握了Python吗? 1. 交换变量 有时候,当我们要交换两个变量的值时,一种常规的方法是创建一个临时变量,然后用它来进行交换。比如: # 输入 a = 5 b ...

糖宝lsh
47分钟前
4
0
咕泡-spring中常用设计模式概述

设计模式就是经验之谈,供后人借鉴,解决一些具有代表性的问题 设计模式来源于生活,反过来帮助我们更好生活 设计模式提升代码的可读性、可扩展性、维护成本、复杂业务问题 千万不要死记硬背...

职业搬砖20年
今天
2
0
day59-20180817-流利阅读笔记-待学习

假·照骗,真·社交焦虑 雪梨 2018-08-17 1.今日导读 发朋友圈之前,不少人为了展现更美好的生活状态会对照片加以“微调”,或是加个滤镜显得逼格更高,或是磨个皮瘦个脸拉个大长腿。现在,国...

aibinxiao
今天
23
0
OSChina 周五乱弹 —— 姑娘在这个节日里表白你接受么?

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @Sharon啊:完全被这个小姐姐圈粉了,学两首她的歌去哈哈 分享王贰浪的单曲《往后余生(翻自 马良)》 《往后余生(翻自 马良)》- 王贰浪 手...

小小编辑
今天
1K
16
为什么HashMap要自己实现writeObject和readObject方法?

为什么HashMap要自己实现writeObject和readObject方法? 如果你有仔细阅读过HashMap的源码,那么你一定注意过一个问题:HashMap中有两个私有方法。 private void writeObject(java.io.Objec...

DemonsI
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部