centos 随机启动脚本编写
先说下问题背景
目前手上开发的产品是springboot微服务的,我们用jenkins来做的部署,部署脚本如下:
1.build脚本 负责从git服务器拉脚本
2.微服务脚本:
#!/bin/sh
appname=${JOB_NAME}
echo "${WORKSPACE}"
echo "Stopping $appname Application"
kill -9 $(netstat -nlp | grep :${port} | awk '{print $7}' | awk -F"/" '{ print $1 }')
rm -f /www/app/$appname-1.0.jar
cp /var/lib/jenkins/workspace/build_folder/$appname/target/$appname.jar /www/app/$appname.jar
chmod 777 /www/app/$appname.jar
\cp /var/lib/jenkins/workspace/build_folder/$appname/src/main/resources/py/* /www/app/
chmod 777 /www/app/*.py
echo "Starting $appname Application"
BUILD_ID=${JOB_NAME}-${port} nohup java -jar -Xms128m -Xmx256m /www/app/$appname.jar --server.port=${port} --spring.profiles.active=${profiles}&
echo "Running $appname Application"
微服务脚本大概就是先去kill -9 掉原有的app进程,然后删除app.jar,copy git下新的app.jar到 /www/app/ 目录下,然后chmod,最后启动jar
对于刚开始的测试项目,这个脚本好像没有什么问题,但是这个里面其实有几个隐藏的问题。
1.当服务器重启,所有服务会down掉。特别对于aws服务器,有时还会被收掉,你的服务down掉了,你都不知道。
2.如果某些服务意外down掉,服务器也不会感受到,需要额外加逻辑去处理这种异常
3.kill -9的方式并不属于进程的正常关闭。
网上搜了很多springboot的部署资料,发现都没有关于这方面的。
所以下面的方法也是自己想出来的,并不代表行业标准解决方案。
通过写 app.service 来启动所有的jar。
好处:
centos 的app.sevice可以随机启动,这点毋容置疑,而且还可以设置down掉之后重启服务,这正是我需要的,但是必须要修改jenkins部署脚本。
先说app.service如何写:
[Unit]
Description=SM EDU Simulator Service
After=sm-edu-api-registry.service
[Service]
User=jenkins
Group=jenkins
ExecStart=/usr/bin/java -jar -Xms128m -Xmx256m /www/app/simulator.jar --server.port=8083 --spring.profiles.active=dev
ExecReload=/usr/bin/ps -ef | grep simulator | grep -v grep | awk '{print $2}' | xargs kill -9 && /usr/bin/java -jar -Xms128m -Xmx256m /www/app/simulator.jar --server.port=8083 --spring.profiles.active=dev
ExecStop=/usr/bin/ps -ef | grep simulator | grep -v grep | awk '{print $2}' | xargs kill -9
Restart=always
[Install]
WantedBy=multi-user.target
After表示在某个进程之后启动
User和Group设置主要是以某个用户去启动
Type=
- 设置进程的启动类型,必须是下列值之一:simple, forking, oneshot, dbus, notify, idle 之一。
- 如果设为"simple"(设置了 ExecStart= 但未设置 BusName= 时的默认值),那么表示 ExecStart= 所设定的进程就是该服务的主进程。 如果此进程需要为其他进程提供服务,那么必须在该进程启动之前先建立好通信渠道(例如套接字),以加快后继单元的启动速度。
- "dbus"(设置了 ExecStart= 与 BusName= 时的默认值)与"simple"类似,不同之处在于该进程需要在 D-Bus 上获得一个由 BusName= 指定的名称。 systemd 将会在启动后继单元之前,首先确保该进程已经成功的获取了指定的 D-Bus 名称。设置为此类型相当于隐含的依赖于 dbus.socket 单元。
- "oneshot"(未设置 ExecStart= 时的默认值)与"simple"类似,不同之处在于该进程必须在 systemd 启动后继单元之前退出。 此种类型通常需要设置 RemainAfterExit= 选项。
- 如果设为"forking",那么表示 ExecStart= 所设定的进程将会在启动过程中使用 fork() 系统调用。这是传统UNIX守护进程的经典做法。 也就是当所有的通信渠道都已建好、启动亦已成功之后,父进程将会退出,而子进程将作为该服务的主进程继续运行。 对于此种进程,建议同时设置 PIDFile= 选项,以帮助 systemd 准确定位该服务的主进程,进而加快后继单元的启动速度。
- "notify"与"simple"类似,不同之处在于该进程将会在启动完成之后通过 sd_notify(3) 之类的接口发送一个通知消息。 systemd 将会在启动后继单元之前,首先确保该进程已经成功的发送了这个消息。 如果设置为此类型,那么 NotifyAccess= 将只能设置为"all"或者"main"(默认)。 注意,目前 Type=notify 尚不能在 PrivateNetwork=yes 的情况下正常工作。
- "idle"与"simple"类似,不同之处在于该进程将会被延迟到所有的操作都完成之后再执行。 这样可以避免控制台上的状态信息与 shell 脚本的输出混杂在一起。
ExecStart=
- 在启动该服务时需要执行的命令行(命令+参数)。有关命令行的更多细节可参见后文的"命令行"小节。 仅在设置了 Type=oneshot 的情况下,才可以设置任意个命令行(包括零个),否则必须且只能设置一个命令行。 多个命令行既可以在同一个 ExecStart= 中设置,也可以通过设置多个 ExecStart= 来达到相同的效果。 如果设为一个空字符串,那么先前设置的所有命令行都将被清空。 如果不设置任何 ExecStart= 指令,那么必须确保设置了 RemainAfterExit=yes 指令。 命令行必须以一个绝对路径表示的可执行文件开始,并且其后的那些参数将依次作为"argv[1] argv[2] ..."传递给被执行的进程。 如果在绝对路径前加上可选的"@"前缀,那么其后的那些参数将依次作为"argv[0] argv[1] argv[2] ..."传递给被执行的进程。 如果在绝对路径前加上可选的"-"前缀,那么即使该进程以失败状态(例如非零的返回值或者出现异常)退出,也会被视为成功退出。 可以同时使用"-"与"@"前缀,且顺序任意。 如果设置了多个命令行,那么这些命令行将以其在单元文件中出现的顺序依次执行。 如果某个无"-"前缀的命令行执行失败,那么剩余的命令行将不会被执行,同时该单元将变为失败(failed)状态。 当未设置 Type=forking 时,这里设置的命令行所启动的进程将被视为该服务的主守护进程。
ExecStartPre=, ExecStartPost=
- 设置在执行 ExecStart= 之前/后执行的命令行。语法规则与 ExecStart= 完全相同。 如果设置了多个命令行,那么这些命令行将以其在单元文件中出现的顺序依次执行。 如果某个无"-"前缀的命令行执行失败,那么剩余的命令行将不会被执行,同时该单元将变为失败(failed)状态。 仅在所有无"-"前缀的 ExecStartPre= 命令全部执行成功的前提下,才会继续执行 ExecStart= 命令。 ExecStartPost= 命令仅在服务已经被成功启动之后才会运行,判断的标准基于 Type= 选项。 具体说来,对于 Type=simple 或 Type=idle 就是主进程已经成功启动;对于 Type=oneshot 来说就是主进程已经成功退出; 对于 Type=forking 来说就是初始进程已经成功退出;对于 Type=notify 来说就是已经发送了"READY=1"; 对于 Type=dbus 来说就是已经取得了 BusName= 中设置的总线名称。 注意,不可将 ExecStartPre= 用于需要长时间执行的进程。 因为所有由 ExecStartPre= 派生的子进程都会在启动 ExecStart= 服务进程之前被杀死。
ExecReload=
- 这是一个可选的指令,用于设置当该服务被要求重新载入配置时所执行的命令行。语法规则与 ExecStart= 完全相同。 另外,还有一个特殊的环境变量 $MAINPID 可以用于表示主进程的PID,例如可以这样使用: /bin/kill -HUP $MAINPID 注意,像上例那样,通过向守护进程发送复位信号,强制其重新加载配置文件,并不是一个好习惯。 因为这是一个异步操作,所以不适用于需要按照特定顺序重新加载配置文件的服务。 我们强烈建议将 ExecReload= 设置为一个能够确保重新加载配置文件的操作同步完成的命令行。
ExecStop=
- 这是一个可选的指令,用于设置当该服务被要求停止时所执行的命令行。语法规则与 ExecStart= 完全相同。 执行完此处设置的命令行之后,该服务所有剩余的进程将会根据 KillMode= 的设置被杀死(参见 systemd.kill(5) 手册)。 如果未设置此选项,那么当此服务被停止时,该服务的所有进程都将会根据 KillMode= 的设置被立即全部杀死。 与 ExecReload= 一样,也有一个特殊的环境变量 $MAINPID 可以用于表示主进程的PID 一般来说,仅仅设置一个结束服务的命令,而不等待其完成,是不够的。 因为当此处设置的命令执行完之后,剩余的进程会被 SIGKILL 信号立即杀死,这可能会导致数据丢失。 因此,这里设置的命令必须是同步操作,而不能是异步操作。
Restart=
- 当服务进程正常退出、异常退出、被杀死、超时的时候,是否重新启动该服务。 "服务进程"是指 ExecStart=, ExecStartPre=, ExecStartPost=, ExecStop=, ExecStopPost=, ExecReload= 中设置的进程。 当进程是由于 systemd 的正常操作(例如 systemctl stop|restart)而被停止时,该服务不会被重新启动。 "超时"可以是看门狗的"keep-alive ping"超时,也可以是 systemctl start|reload|stop 操作超时。
- 该选项可以取下列值之一:no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, always "no"(默认值)表示不会被重启。"always"表示会被无条件的重启。 "on-success"表示仅在服务进程正常退出时重启,所谓"正常退出"是指: 退出码为"0",或者进程收到 SIGHUP, SIGINT, SIGTERM, SIGPIPE 信号并且退出码符合 SuccessExitStatus= 的设置。 "on-failure"表示仅在服务进程异常退出时重启,所谓"异常退出"是指: 退出码不为"0",或者进程被强制杀死(包括"core dump"以及收到 SIGHUP, SIGINT, SIGTERM, SIGPIPE 之外的其他信号), 或者进程由于看门狗或者 systemd 的操作超时而被杀死。 对于 on-failure, on-abnormal, on-abort, on-watchdog 的分别适用于哪种异常退出。
Unit 的状态
systemctl status命令用于查看系统状态和单个 Unit 的状态
[root@DaMoWang ~]# systemctl status # 显示系统状态
[root@DaMoWang ~]# sysystemctl status httpd.service # 显示单个 Unit 的状态
[root@DaMoWang ~]# systemctl -H root@192.168.94.104 status httpd.service # 显示远程主机的某个 Unit 的状态
Unit 管理
对于用户来说,最常用的是下面这些命令,用于启动和停止 Unit(主要是 service)

[root@DaMoWang ~]# systemctl start httpd.service # 立即启动一个服务
[root@DaMoWang ~]# systemctl stop httpd.service # 立即停止一个服务
[root@DaMoWang ~]# systemctl restart httpd.service # 重启一个服务
[root@DaMoWang ~]# systemctl kill httpd.service # 杀死一个服务的所有子进程
[root@DaMoWang ~]# systemctl reload httpd.service # 重新加载一个服务的配置文件
[root@DaMoWang ~]# systemctl daemon-reload # 重载所有修改过的配置文件
[root@DaMoWang ~]# systemctl show httpd.service # 显示某个 Unit 的所有底层参数
[root@DaMoWang ~]# systemctl show -p CPUShares httpd.service # 显示某个 Unit 的指定属性的值
[root@DaMoWang ~]# systemctl set-property httpd.service CPUShares=500 # 设置某个 Unit 的指定属性
在最后遇到一个坑,发现jenkins没有权限执行systemctl
为了不破坏安全性。
最后解决方案为 在系统级别加入service,但是在部署时,不用service。jenkins还是保持之前的脚本。
centos 随机启动脚本编写的更多相关文章
- redhat nginx随机启动脚本
开机自动启动nginx 1. 扔脚本进去/etc/init.d/ 2. 授权 chmod +x nginx 3. 一旦抛出:binsh^M错误就执行编码改写 设置do ...
- rsync随机启动脚本
服务端 #!/bin/sh # chkconfig: # description: Saves and restores system entropy pool for \ #create by xi ...
- nginx的编译安装以及启动脚本编写
Nginx的编译安装和启动脚本的编写 Nginxd的功能强大,可以实现代理.负载均衡等企业常用的功能.下面介绍一下nginx的编译安装方法: 1. 下载 官方下载地址:http://nginx.org ...
- [转]CentOS开机启动脚本
转载自http://www.2cto.com/os/201306/220559.html 我的一个Centos开机自启动脚本的制作 一.切换到/etc/init.d/ 二.制作sh脚本 v ...
- nginx二进制编译-启动脚本编写
首先先把这个文件上传到root目录下,并解压 #tar zxf nginx-1.11.2.tar.gz 写脚本 # vi nginx-running.sh 内容如下 #!/bin/bash #chkc ...
- centos LNMP第一部分环境搭建 LAMP LNMP安装先后顺序 php安装 安装nginx 编写nginx启动脚本 懒汉模式 mv /usr/php/{p.conf.default,p.conf} php运行方式SAPI介绍 第二十三节课
centos LNMP第一部分环境搭建 LAMP安装先后顺序 LNMP安装先后顺序 php安装 安装nginx 编写nginx启动脚本 懒汉模式 mv /usr/local/php/{ ...
- linux shell 之尝试编写 企业级 启动脚本
企业Shell面试题10:开发企业级MySQL启动脚本 说明: MySQL启动命令为: 1 /bin/sh mysqld_safe --pid-file=$mysqld_pid_file_path 2 ...
- 自己编写服务启动脚本(一):functions文件详细分析和说明
本文目录: 1.几个显示函数2.action函数3.is_true和is_false函数4.confirm函数5.pid检测相关函数 5.1 checkpid.__pids_var_run和__pid ...
- Centos 配置开机启动脚本启动 docker 容器
Centos 配置开机启动脚本启动 docker 容器 Intro 我们的 Centos 服务器上部署了好多个 docker 容器,因故重启的时候就会导致还得手动去手动重启这些 docker 容器,为 ...
随机推荐
- Canvas恢复布局
package com.loaderman.customviewdemo; import android.content.Context; import android.graphics.Canvas ...
- (三)java虚拟机内存管理和线程独占区和线程共享区
一.内存管理 二.线程独占区之程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里,字节 ...
- php-fpm优化参数介绍
1.php-fpm优化参数介绍他们分别是:pm.pm.max_children.pm.start_servers.pm.min_spare_servers.pm.max_spare_servers. ...
- iOS-检测网络可连接性
#pragma mark - 监测网络的可链接性+ (void)netWorkReachabilityWithURLString:(NSString *)strUrl{ AFHTTPReques ...
- 《C语言程序设计》学习笔记(二)
第八章 函数 函数的基本概念 定义:函数由函数名.参数和函数体组成. 函数定义的一般形式: 类型说明符 函数名(形式参数声明) { [说明与定义部分] 语句: } 说明: 1.类型说明符用来说明函数的 ...
- VMware15安装Centos7超详细过程
本篇文章主要介绍了VMware安装Centos7超详细过程(图文),具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.软硬件准备 软件:推荐使用VMwear15,我用的是VMwear 15 镜像: ...
- python return逻辑判断表达式(21)
一.return逻辑判断表达式 and and:遇假则假,所以前面为假就不执行和判断后面直接返回假:前面为真则继续判断执行后面直到表达式结束或者出现假为止; # !usr/bin/env python ...
- 【leetcode算法-简单】53. 最大子序和
[题目描述] 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4],输出: 6解释: ...
- stub_status监控Nginx使用情况!
stub_status监控Nginx使用情况! 查看nginx安装的模块! # /usr/local/nginx/sbin/nginx -V nginx version: nginx/1.8.1 bu ...
- Jupyter修改工作目录(Anaconda环境)
Anaconda安装时未添加环境变量 1.打开Anaconda Prompt 输入jupyter notebook --generate-config (base) C:\Users\Sroxi> ...