狂创客圈 经典图书 : 《Netty Zookeeper Redis 高并发实战》 面试必备 + 面试必备 + 面试必备 【博客园总入口 】
疯狂创客圈 经典图书 : 《SpringCloud、Nginx高并发核心编程》 大厂必备 + 大厂必备 + 大厂必备 【博客园总入口 】
入大厂+涨工资必备: 高并发【 亿级流量IM实战】 实战系列 【 SpringCloud Nginx秒杀】 实战系列 【博客园总入口 】
组件 | 链接地址 |
---|---|
【必须】 虚拟机Linux 开发环境准备 | |
Linux openresty 安装 | Linux openresty 安装 |
【必须】Linux Redis 安装(带视频) | Linux Redis 安装(带视频) |
【必须】Linux Zookeeper 安装(带视频) | Linux Zookeeper 安装, 带视频 |
Windows Redis 安装(带视频) | Windows Redis 安装(带视频) |
RabbitMQ 离线安装(带视频) | RabbitMQ 离线安装(带视频) |
ElasticSearch 安装, 带视频 | ElasticSearch 安装, 带视频 |
Nacos 安装(带视频) | Nacos 安装(带视频) |
【必须】Eureka | Eureka 入门,带视频 |
【必须】springcloud Config 入门,带视频 | springcloud Config 入门,带视频 |
【必须】SpringCloud 脚手架打包与启动 | SpringCloud脚手架打包与启动 |
Linux 自启动 假死自启动 定时自启 | Linux 自启动 假死启动 |
在linux的使用过程中,我们经常会碰到需要将某个自定义的应用程序设置为开机自启动以节省操作时间,这里提供两个设置开机自启动的方法。
ubuntu在开机过程之后,会执行/etc/rc.local(注意/etc/init.d中也有个rc.local,不要弄混了)文件中的脚本程序,初始情况下,这个文件内容是这样的:
downey@ubuntu:~$ cat /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
并不包含其它内容,用户可以在里面添加需要开机执行的脚本命令,这里以diodon粘贴板工具为例,如果我要开机运行diodon进程,在文本中添加:
downey@ubuntu:~$ cat /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
./usr/bin/diodon &
exit 0
看到这里有些盆友就要问了,为什么要在执行命令后面加&?
在shell执行命令后加&是为了让应用程序在后台运行,rc.local也是一个脚本,主进程在运行这个脚本时必须能够返回,如果在这个脚本里面执行了一些死循环或者其他无法返回的任务,整个系统就很可能卡死在这里,无法启动,所以在这里运行的用户程序必须是能够返回或者本身就使用一些后台运行的进程。
经过上面的添加,在下次重启的时候,使用命令:
downey@ubuntu:~$ ps -ef |grep "diodon"
downey 2097 1880 0 22:53 ? 00:00:04 diodon
downey 2937 2842 0 23:27 pts/2 00:00:00 grep --color=auto diodon
就可以看到diodon进程已经在后台运行。
既然有添加,就必须得有删除,其实以rc.local的删除方式很简单,直接删除rc.local中用户添加的部分即可。
需要提醒的是,在操作系统文件时,做备份是非常必要的
第二种方式就是将自己的用户脚本添加到/etc/init.d并链接到自启动程序当中。
还是以diodon软件来举例,我编辑一个运行diodon的脚本:
#!/bin/bash
./usr/bin/diodon
将其命名为diodon.sh,并用指令:
chmod +x diodon.sh
sudo cp diodon.sh /etc/init.d/
将文件放到/etc/init.d目录中,然后将diodon,sh脚本链接到开机运行序列中:
cd /etc/init.d
sudo update-rc.d diodon.sh defaults 96
insserv: warning: script 'diodon' missing LSB tags and overrides
这样重新启动时,就可以看到diodon.sh正在运行了。
sudo update-rc.d diodon.sh defaults 96
在这条指令中,update-rc.d是一个系统的链接工具。
而defaults 96则是指定了脚本的开机顺序,数字为0-99,数字越大执行优先级越低,用户添加的程序最好选择低优先级的执行顺序,因为很可能我们的用户程序会依赖一些系统的应用进程,例如如果应用程序要使用到网络部分,就先得让网络后台程序先初始化完毕。
看到这里,细心的朋友已经发现了,在链接脚本时有一个警告:
insserv: warning: script 'diodon' missing LSB tags and overrides
作为一个菜鸟而言,是不敢忽视任何警告的,所以只好求助google,解决办法是在自己的脚本中的#!/bin/bash下添加:
### BEGIN INIT INFO
# Provides: downey
# Required-Start: $local_fs $network
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: tomcat service
# Description: tomcat service daemon
### END INIT INFO
添加这些的目的是告诉系统一些关于这个启动脚本的具体信息,其中比较重要的有这几项:
# Required-Start: 运行这个脚本需要的环境
# Required-Start: 停止这个脚本需要的环境
# Default-Start: 提供运行的运行级别
# Default-Stop: 不运行的运行级别
# Description: 描述
关于linux下的运行级别参考:linux运行级别
既然有添加就必然有删除,如果需要删除自定义开机运行脚本,输入:
sudo update-rc.d -f diodon remove
上面提到的两种方式适用于经典的system V控制系统启动和关闭的情况,但是目前(2018年10月)在大多数发行版上都开始使用了systemd的系统软件控制方式,包括Ubuntu16,centos.systemd系统管理着linux下的进程运行,属于应用程序,不属于linux内核的范畴。
在systemd系统上设置开机自启动的方式也是非常简单的(尽管systemd这套软件管理工具并不简单)。
这里要注意的是,systemd是linux发行版上的预装工具,用来管理系统软件的启动运行和结束,所以通常来说,这套东西是依赖于发行版的,如果系统使用了这一套工具,那么就可以使用它来管理进程,如果不是,即使你安装了它,它也不会被默认配置为系统管理工具。
查看系统是否使用systemd工具我们可以使用如下的指令:
systemd --version
如果系统返回如下类似的信息,表明该系统是由systemd工具来管理软件:
systemd 232
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN
对软件的管理主要是同通过systemd工具中的systemctl命令,相比于之前的system V的控制方式,systemd显得更加简洁明了,对用户更加友好,拿httpd来举例:
开启httpd服务:
sudo systemctl start httpd
设置httpd服务自启动:
sudo systemctl enable httpd
至于关闭和取消自启动,大家心里应该有数了吧。
我们再回到重点,设置开机自启动。
我们要为目标设置一个配置文件,其实这是可以预想到的,linux作为一个复杂的系统,开机自启动涉及到的依赖、运行级别、运行环境等等问题肯定需要用户去指定,在启动的时候系统才知道怎么正确地去运行软件。这个配置文件固定以.service作为后缀,比如我们如果要运行/home/downey目录下的test.sh脚本,我们可以添加一个配置文件***test.service***:
[Unit]
Description=
Documentation=
After=network.target
Wants=
Requires=
[Service]
ExecStart=/home/downey/test.sh
ExecStop=
ExecReload=/home/downey/test.sh
Type=simple
[Install]
WantedBy=multi-user.target
将文件放在/usr/lib/systemd/system 或者 /etc/systemd/system目录下,然后可以测试一下:
sudo systemctl start test.service
然后你可以查看你的/home/downey/test.sh脚本是否已经运行,如果已经运行表示配置文件没有问题。然后可以键入:
sudo systemctl enable test.service
设置test脚本开机启动。如果上一步没有出问题,这一步基本上也不会有什么问题,系统会打印出如下信息:
Created symlink /etc/systemd/system/multi-user.target.wants/test.service → /usr/lib/systemd/system/test.service.
可以看到,这里在/etc/systemd/system/multi-user.target.wants/目录下创建了一个/usr/lib/systemd/system/test.service文件的软链接,到这里设置开机自启动就完成了。
在上面的配置文件中,为了演示起见,我将一些本测试脚本不需要但是比较重要的配置项也写了出来,其实如果不需要可以删除,但是[Unit]/[Service]/[Install]这三个标签需要保留。
我们来一个个简单介绍一下配置项:
Description:运行软件描述
Documentation:软件的文档
After:因为软件的启动通常依赖于其他软件,这里是指定在哪个服务被启动之后再启动,设置优先级
Wants:弱依赖于某个服务,目标服务的运行状态可以影响到本软件但不会决定本软件运行状态
Requires:强依赖某个服务,目标服务的状态可以决定本软件运行。
ExecStart:执行命令
ExecStop:停止执行命令
ExecReload:重启时的命令
Type:软件运行方式,默认为simple
WantedBy:这里相当于设置软件,选择运行在linux的哪个运行级别,只是在systemd中不在有运行级别概念,但是这里权当这么理解。
如果有多项,用逗号作为分隔。
定时监测与假死重启的方式,使用crontab 定时任务监测进程,并且实时重启。
举个例子,
vi /usr/local/presto_monitor.sh
#!/bin/sh
command="/usr/local/Presto/presto-server-0.100/bin/launcher run"
appname=presto-server
logfile=/usr/local/log/presto_monitor.log
#返回 ps -ef 出来的所有字符串中含有 $appname 的进程个数
checkrun=`ps -ef | grep $appname | grep -v "grep" | wc -l`
echo "$appname 运行监测开始….."
#ps -ef | grep launcher | grep -v "grep" | wc -l
#while true
#do
#echo $checkrun
if [ 0 = $checkrun ]; then
#进程不存在
time2=$(date "+%Y-%m-%d %H:%M:%S")
echo "$appname 服务宕机,正在重新启动"
#echo "$appname 服务宕机,宕机时间为:"$time2>>$appname.log
#./$appname $appname &logfile
nohup $command > $logfile 2>&1 &
#nohup /usr/local/Presto/presto-server-0.100/bin/launcher run > presto_run.log 2>&1 &
sleep 1
pid=$(ps -ef | grep -v 'grep' | egrep $appname| awk '{printf $2 " "}')
echo "$appname ($pid)重新启动成功!!!"
else
#进程存在
sleep 1
pid=$(ps -ef | grep -v 'grep' | egrep $appname| awk '{printf $2 " "}')
echo "$appname ($pid) 服务运行正常...持续监控中"
fi
time=$(date "+%Y-%m-%d %H:%M:%S")
echo "本轮监测完毕,当前时间为:"$time
#done
#这里有一行
使用nohup命令后台运行命令之后,需要使用exit正常退出当前账户,这样才能保证命令一直在后台运行(es head插件有这个问题)。
command>out.file是将command的输出重定向到out.file文件,即输出内容不打印到屏幕上,而是输出到out.file文件中。如果不想要输出文件则修改 out.file 为 /dev/null。
2>&1 是将标准出错重定向到标准输出,这里的标准输出已经重定向到了out.file文件,即将标准出错也输出到out.file文件中。
最后一个&, 是让该命令在后台执行。
0-输入 1-输出 2-错误
crontab:定时任务的守护进程,精确到分,设计秒的我们一般写脚本 -->相当于闹钟
日志文件: ll /var/log/cron*
编辑文件: vim /etc/crontab
进程:ps -ef | grep crond ==> /etc/init.d/crond restart
作用:定时备份,实时备份
Linux下的任务调度分为两类,系统任务调度和用户任务调度。
(1) 系统任务调度:系统周期性所要执行的工作,比如写缓存数据到硬盘、日志清理等。
在/etc/crontab文件,这个就是系统任务调度的配置文件。
(2) 用户任务调度:用户定期要执行的工作,比如用户数据备份、定时邮件提醒等。
用户可以使用 crontab 工具来定制自己的计划任务。
在crontab 文件都被保存在/var/spool/cron目录中。其文件名与用户名一致
1.系统定时任务:例如清理系统日志,清理系统缓存 -->不过多的关注
查询系统定时处理任务的路径:
路径1:
cd /etc/logrotate.d/ -->可以写定时任务
less syslog
路径2:
cat /etc/crontab -->不推荐使用,但是可以看格式
路径3:
ls /etc/ | grep cron*
anacrontab
cron.d -->同路径2 ,可以写定时任务
cron.daily
cron.deny -->控制普通用户使用定时任务crontab
cron.hourly
cron.monthly
crontab
cron.weekly
2.用户的定时任务 -->关注重点
/etc/crontab -l
如果没有权限,
sudo groupadd root:crontab
sudo chown root:crontab /var/spool/cron/crontabs/
启动 crond
service crond start
*/10 * * * *
cron 的主配置文件是 /etc/crontab,它包括下面几行:
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
前四行是用来配置 cron 任务运行环境的变量。 SHELL 变量的值告诉系统要使用哪个 shell 环境(在这个例子里是 bash shell);
PATH 变量定义用来执行命令的路径。
cron 任务的输出被邮寄给 MAILTO 变量定义的用户名。
如果 MAILTO 变量被定义为空白字符串(MAILTO=""),电子邮件就不会被寄出。
HOME 变量可以用来设置在执行命令或脚本时使用的主目录。
/etc/cron.allow和/etc/cron.deny 文件被用来限制对 cron 的使用。
这两个使用控制文件的格式都是每行一个用户。 两个文件都不允许空格。
如果使用控制文件被修改了,cron 守护进程(crond)不必被重启。
使用控制文件在每次用户添加或删除一项 cron 任务时都会被读取。
无论使用控制文件中的规定如何,root 都总是可以使用 cron。
如果 cron.allow 文件存在,只有其中列出的用户才被允许使用 cron,并且 cron.deny 文件会被忽略。
如果 cron.allow 文件不存在,所有在 cron.deny 中列出的用户都被禁止使用 cron。
安装crontab:
yum install crontabs
crontab服务操作说明:
/sbin/service crond start //启动服务
/sbin/service crond stop //关闭服务
/sbin/service crond restart //重启服务
/sbin/service crond reload //重新载入配置
查看crontab服务状态:
service crond status
手动启动crontab服务:
service crond status
查看crontab服务是否已设置为开机启动,执行命令:
方法一: 界面启动 ntsysv
方法二: 加入开机自动启动: chkconfig –level 35 crond on
crontab -l查看定时任务列表
编辑定时任务
crontab –e
==》vim /var/spool/cron/root
每隔2分钟输出时间到文件
*/2 * * * * echo date
>> $HOME>test.txt
crontab -r 删除定时任务
==> 从/var/spool/cron目录中删除用户的crontab文件
==> 如果不指定用户,则默认删除当前用户的crontab文件
crontab –i 在删除用户的crontab文件时给确认提示
备份crontab文件
crontab -l > $HOME/mycron
系统级任务调度与用户级任务调度
root用户的任务调度操作可以通过“crontab –uroot –e”来设置,也可以将调度任务直接写入/etc/crontab文件,需要注意的是,如果要定义一个定时重启系统的任务,就必须将任务放到/etc/crontab文件,即使在root用户下创建一个定时重启系统的任务也是无效的。
其他注意事项
当crontab突然失效时,可以尝试/etc/init.d/crond restart解决问题。或者查看日志看某个job有没有执行/报错tail -f /var/log/cron。
千万别乱运行crontab -r。它从Crontab目录(/var/spool/cron)中删除用户的Crontab文件。删除了该用户的所有crontab都没了。
在crontab中%是有特殊含义的,表示换行的意思。如果要用的话必须进行转义%,如经常用的date ‘+%Y%m%d’在crontab里是不会执行的,应该换成date ‘+%Y%m%d’
最后.crontab箴言
1.环境变量问题,例如crontab不能识别Java的环境变量
crontab执行shell时,只能识别为数不多的环境变量,普通的环境变量是无法识别的,所以在编写shell时,最好使用export重新声明变量,确保脚本执行。
2.命令的执行最好用脚本
3.脚本权限加/bin/sh,规范路径/server/scripts
4.时间变量用反斜线转义,最好用脚本
5.定时任务添加注释
6.>/dev/null 2>&1 ==> &>/dev/null,别随意打印日志文件
7.定时任务里面的程序脚本尽量用全路径
8.避免不必要的程序以及命令输出
9.定时任务之前添加注释
10.打包到文件目录的上一级
用户所建立的crontab文件中,每一行都代表一项任务,每行的每个字段代表一项设置,它的格式共分为六个字段,前五段是时间设定段,第六段是要执行的命令段,格式如下:
minute hour day month week command
其中:
1、minute: 表示分钟,可以是从0到59之间的任何整数;
2、hour:表示小时,可以是从0到23之间的任何整数;
3、day:表示日期,可以是从1到31之间的任何整数;
4、month:表示月份,可以是从1到12之间的任何整数;
5、week:表示星期几,可以是从0到6之间的任何整数,这里的0代表星期日;
6、command:要执行的命令,可以是系统命令,也可以是自己编写的脚本文件。
前五个时间设定段,可以含如下特殊字符:
1、星号(*):代表所有可能的值,例如month字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作;
2、逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”;
3、中杠(-):可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”;
4、正斜线(/):可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。同时正斜线可以和星号一起使用,例如*/10,如果用在minute字段,表示每十分钟执行一次。
一.文件位置
位置一般在/var/spool/cron/下,如果你是root用户,那下面有个root文件,建议日常备份,避免误删除导致crontab 文件丢失;
二.日志文件位置
默认情况下,crontab中执行的日志写在/var/log下,如:
#ls /var/log/cron*
/var/log/cron /var/log/cron.1 /var/log/cron.2 /var/log/cron.3 /var/log/cron.4
crontab的日志比较简单,当crond执行任务失败时会给用户发一封邮件。恰巧在我们的一台服务器上发现一个任务没有正常执行,而且crond发邮件也失败了。通过看mail的日志,看到是磁盘空间不足造成的。
可以将每条 crontab中的任务增加自己的日志,有利于查找执行失败原因。
0 6 * * * //root/script/ss.sh >> /root/for_crontab/mylog.log 2>&1
把错误输出和标准输出都输出到mylog.log中。
疯狂创客圈 - Java高并发研习社群,为大家开启大厂之门