1、在系统启动阶段,由系统初始化脚本启动。
2、由inetd超级服务器启动。
3、cron守护进程按规则定期执行一些程序,启动的程序同样作为守护进程运行。
4、at命令用于指定将来某个时刻的程序执行。
5、守护进程还可以用户从用户终端或在前台或在后台启动。
昨天在Linux做个进程守护脚本时发生了几个小问题,实属不该。先总结如下,在以后的实践中一个避免这样的问题。同时针对cron,再次深入学习实践。
1、换行符问题
脚本与运行报错“:badinterpreter:Nosuchfileordirectory”。
脚本在windows下编辑,有几条命令是直接复制过来使用的,虽然vs code可以在右下角选择行尾序列,但是在实际运行时还是提示无法识别/r,每一行都多了个^M 。
\r\n: Dos和Windows采用回车+换行(CR+LF)表示下一行,即^M$
\n: 而UNIX/Linux采用换行符(LF)表示下一行
\r: 苹果机(MAC OS系统)则采用回车符(CR)表示下一行
2、= 赋值问题
笔者在使用if条件表达式时,知道条件要放在方括号之间,并且要有空格。误以为变量赋值=也要空格,运行时发现变量无法识=识别,后来才知道变量赋值=不能有空格。
3、cron定时任务的环境变量问题
用户的crontab定时任务不会使用默认的变量, 需要写全路径,包括crontab调用的脚本里面 。而系统cron定时任务是由定义环境变量的。MAILTO是表示例行性命令发生错误时,会将错误讯息邮件传给root,服务器中关闭postfix,导致邮件发送不成功,全部小文件堆积在/var/spool/postfix/maildrop/里面。
4、cron中执行的程序有输出内容,输出内容会以邮件形式发给cron的用户,而sendmail没有启动所以就产生了/var/spool/mail目录下的那些文件,日积月累可能撑破磁盘。在cron中命令后面加上 >/dev/null 2>&1 来不输出。
5、crontab中的指令需要root,配置/etc/sudoers文件来保证sudo可用,其实可用使用系统任务计划,指定root来执行即可。
最后,笔者专注于使用cron,现在在以前的文章(树莓派上测试)- Linux crontab定时任务详细分解 的基础上,在腾讯云服务器centos上补充以下cron的知识。
用户计划任务 :
1、crond时cron的守护进程,crond是由多个配置文件和系统范围内的文件控制的,每个用户对应一个配置文件。crond守护进程是cronie软件的一部分。用户的配置文件在/var/spool/cron/username。
2、crontab命令
crontab -e 编辑当前用户的定时计划
crontab -l 列出当前用户的定时计划
crontab -r 删除当前用户的所有定时计划
crontab filename 删除当前用户的所有定时计划,并从filename中读取作业,如果未指定任何文件,则使用stdin 。
3、格式,另外*/x表示间隔x个周期。 用户计划任务没有user-name字段!
*/7 9-16 * jul 5 command表示7月的每周五的上午9到下午5点 间,每七分钟执行一次。
系统计划任务:
1、系统cron不是由crontab来执行的,而是在一组配置文件中定义的,配置文件多了一个字段-用户字段,指定作业在那个用户下运行。
2、系统计划任务储存在/etc/crontab、 /etc/cron.d/* 以及/etc/cron.* ,/etc/crontab的语法规则参照上面的图。 /etc/cron.d/时软件产生的一些更新任务,一般不在里面做 *** 作。
3、预定义作业,cron.daily、cron.hourly、cron.monthly、cron.weekly下面储存的是可执行脚本。
/etc/cron.hourly/*脚本是使用runparts命令从/etc/cron.d/0hourly中定义的,表示每小时的第一分钟将 /etc/cron.hourly/下面的脚本全部执行。
/etc/cron.daily、 /etc/cron.monthly、 /etc/cron.weekly也是使用runparts命令,但是是从/etc/anacrontab中执行的。
4、/etc/anacrontab语法规则
START_HOURS_RANGE=3-22,表示Anacron jobs will start between 3am and 10pm.
RANDOM_DELAY=45,The RANDOM_DELAY variable denotes the maximum number of minutes that will be added to the delay in minutes variable which is specified for each job.
上图中,对于 /etc/cron.daily,那么delay 会是 5 minutes + RANDOM_DELAY 。
接下来就是4个重要的参数:
period in days ,delay in minutes ,job-identifier, command
The period in days variable表示执行周期,每多少天运行一次该作业。
delay in minutes:上面提到的执行的延时,启动作业前,crond等待的时间。
job-identifier:标识作业的唯一名称,用做日志记录。是/var/spool/anacron中文件的名称,检查该作业是否已运行,/etc/anacrontab启动作业时,会更新此文件的时间戳,检查作业上次运行的时间。anacron 会分析现在的时间与时间记录文件所记载的上次执行 anacron 的时间,将两者进行比较,如果两个时间的差值超过 anacron 的指定时间差值(一般是 1 天、7 天和一个月),就说明有定时任务没有执行,这时 anacron 会介入并执行这个漏掉的定时任务,从而保证在关机时没有执行的定时任务不会被漏掉。这也是为什么/etc/cron.{daily,weekly,monthly} 目录中的定时任务只会被 anacron 调用,而 /etc/cron.hourly/被cron调用 。
command:执行命令可以是普通命令或者脚本。
5、cron的访问控制
/etc/cron.allow、 /etc/cron.deny ,以决定哪些用户可以使用调度服务。
如果只有cron.deny文件,而cron.allow文件不存在,则除了黑名单之外的所有用户都可以使用;
如果只有cron.allow文件存在,而cron.deny文件不存在时,则只有白名单用户才可以使用,,包括root。
如果两个文件都存在,则忽略cron.allow文件。
如果两个文件都不存在,每个用户都可以访问。
在我们日常运维中,写脚本监控一个进程是比较常见的 *** 作,比如我要监控mysql进程是否消失,如果消失就重启mysql,用下面这段代码就可以实现:#!/bin/sh
Date=` date '+%c'`
while :
do
if ! psaux | grep -w mysqld | grep -v grep >/dev/null 2>&1
then
/etc/init.d/mysqldstart
echo $Datemysqldwasreboot >>/var/log/reboot_mysql.log
fi
done
本篇这是以mysql为例子,但实际中如果是监控的脚本出了问题,报警没发出来,那就比较尴尬了,所以为保证我们的检查脚本能实时运行,我们需要一个进程来守护这个脚本,这就是我们今天要说的主题,如何给脚本写一个daemon,我们先上代码:
#!/usr/bin/python
import subprocess
from daemonimport runner
cmd = "/root/demo_script/restart_mysql.sh"
class App():
def __init__(self):
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = '/tmp/hello.pid'
self.pidfile_timeout = 5
def start_subprocess(self):
return subprocess.Popen(cmd, shell=True)
def run(self):
p = self.start_subprocess()
while True:
res = p.poll()
if resis not None:
p = self.start_subprocess()
if __name__ == '__main__':
app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()
脚本比较简单,没什么特别的逻辑,关于daemon这个模块如何使用,我这里给出官方的解释,注意哟,是英文的,我就不翻译了,如果有生词就查查字典,就当多学几个了单词吧。
__init__(self, app)
| Setuptheparametersof a new runner.
|
| The `app` argumentmusthavethefollowingattributes:
|
| * `stdin_path`, `stdout_path`, `stderr_path`: Filesystem
|pathsto openand replacetheexisting `sys.stdin`,
|`sys.stdout`, `sys.stderr`.
|
| * `pidfile_path`: Absolutefilesystempathto a filethat
|willbeusedas thePIDfilefor thedaemon. If
|``None``, noPIDfilewillbeused.
|
| * `pidfile_timeout`: Usedas thedefault acquisition
|timeoutvaluesuppliedto therunner's PIDlockfile.
|
| * `run`: Callablethatwillbeinvokedwhenthedaemonis
|started.
|
| do_action(self)
| Performtherequestedaction.
|
| parse_args(self, argv=None)
| Parsecommand-linearguments.
这样就完成了,守护进程的启动比较高大上,输入以上代码后,可以直接在终端输入:
#python monitor.py start
当然还有stop,restart等参数。
这里我介绍的是其中一个应用场景,实际中可以灵活运用,比如1台服务器上启动的程序过多,环境配置比较复杂,就可以先启动daemon进程,然后通过daemon来启动其它所有应用程序,就不用一个一个应用程序启动了,这篇就到这里,有问题可以给我留言。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)