linux中创建系统服务

500 阅读7分钟

一、linux中如何创建系统服务?

1.1使用systemd创建系统服务(现代 Linux 系统常用方法)

步骤一:编写服务单元文件(.service

服务单元文件通常存放在/etc/systemd/system/目录下。例如,创建一个名为my_service.service的文件,内容可以如下:

       [Unit]
       Description=My Custom Service
       After=network.target
       [Service]
       Type=simple
       ExecStart=/usr/bin/my_service_executable
       Restart=on - failure
       [Install]
       WantedBy=multi - user.target

在[Unit]部分:

  1. Description是对服务的简单描述,用于在查看服务状态等操作时提供信息。

  2. After指定了此服务应该在某个目标(target)之后启动,这里network.target表示在网络相关服务启动之后再启动本服务,以确保服务运行时网络已可用。

在[Service]部分:

  1. Type定义了服务的启动类型,simple表示这是一个简单的服务,systemd会认为ExecStart指定的进程就是此服务的主进程。

  2. ExecStart指定了服务启动时要执行的命令,这里假设/usr/bin/my_service_executable是服务的可执行程序路径。

  3. Restart设置了服务在何种情况下重启,on - failure表示当服务执行失败时自动重启。

在[Install]部分:

WantedBy定义了服务在哪个系统目标下被启用,multi - user.target表示在多用户模式下启用此服务。

步骤二:重新加载systemd配置

编写完服务单元文件后,需要让systemd重新加载配置,使用命令systemctl daemon - reload。这一步很重要,因为systemd需要读取新的服务定义才能对新服务进行管理。

步骤三:启动和启用服务

1)可以使用systemctl start my_service来启动服务。这里my_service是服务的名称,即服务单元文件中去掉.service后缀的部分。

2)若要设置服务在开机时自动启动,使用systemctl enable my_service。这会在/etc/systemd/system/multi - user.target.wants/目录下创建一个指向my_service.service的符号链接,从而在系统启动进入多用户模式时自动启动该服务。

1.2传统的init脚本方式(在较旧的 Linux 系统中使用)

步骤一:编写init脚本

1)init脚本通常存放在/etc/init.d/目录下。例如,创建一个名为my_service的脚本,脚本内容可以如下:

       #!/bin/sh
       ### BEGIN INIT INFO
       # Provides:          my_service
       # Required - Start:    $local_fs $network
       # Required - Stop:     $local_fs $network
       # Default - Start:     2 3 4 5
       # Default - Stop:      0 1 6
       # Short - Description: My Custom Service
       # Description:       This is a custom service for demonstration purposes.
       ### END INIT INFO
       case "$1" in
         start)
           /usr/bin/my_service_executable &
           ;;
         stop)
           killall my_service_executable
           ;;
         *)
           echo "Usage: $0 {start|stop}"
           exit 1
           ;;
       esac
       exit 0
  1. 脚本开头部分的### BEGIN INIT INFO### END INIT INFO之间的内容是用于提供服务的相关信息,如服务名称、启动和停止所需的条件、默认启动和停止的运行级别等。

  2. case语句中:

a.当参数为start时,使用/usr/bin/my_service_executable &启动服务,&表示在后台运行服务进程。

b.当参数为stop时,使用killall my_service_executable来停止服务。

c.对于其他参数,打印使用说明并退出。

步骤二:设置脚本权限和链接(如果需要)

  1. 首先,使用chmod +x /etc/init.d/my_service为脚本添加可执行权限。

  2. 然后,根据系统的运行级别设置,可以将脚本链接到相应的运行级别目录。例如,在基于SysV的系统中,如果希望服务在运行级别 2、3、4、5 启动,可以使用命令ln - s /etc/init.d/my_service /etc/rc2.d/S99my_service等(数字99表示启动顺序,数字越小启动越早)。不过,在现代很多 Linux 系统中,这种基于运行级别的方式已经逐渐被systemd所替代。

二、etc/init.d/ 与/usr/local/etc/rc.d/和/etc/systemd/system/下创建的服务有什么异同?

2.1相同点

1) 服务管理目的:这三个目录下创建的内容都是用于管理系统服务。无论是在传统的/etc/init.d//usr/local/etc/rc.d,还是在现代的/etc/systemd/system/目录下,其核心目的都是确保系统相关的服务能够顺利启动、停止、重启以及在系统启动或关闭过程中按照一定的规则运行。

2) 提供基本操作功能都可以实现对服务的基本操作。例如,启动服务(在/etc/init.d/下可以使用/etc/init.d/service_name start,在/etc/systemd/system/下可以使用systemctl start service_name)、停止服务(类似地有/etc/init.d/service_name stop和systemctl stop service_name)和重启服务(/etc/init.d/service_name restart和systemctl restart service_name)。

2.2不同点

2.2.1启动机制与运行级别关联

2.2.1.1、/etc/init.d//usr/local/etc/rc.d
  1. 基于传统的init系统,这些目录下的服务脚本与系统运行级别紧密相关。运行级别代表了系统的不同操作模式,例如运行级别 3 通常是多用户命令行模式,运行级别 5 是带有图形界面的多用户模式。服务脚本通过在不同运行级别目录(如/etc/rc.d/rc3.d//etc/rc.d/rc5.d/)中创建符号链接来控制在相应运行级别下的启动和停止。这些符号链接的命名有一定规则,如以S开头表示启动(S后面的数字表示启动顺序),以K开头表示停止。这种方式使得服务的启动和停止依赖于系统所处的运行级别设置。

  2. 例如,在/etc/init.d/中有一个服务脚本httpd,如果希望它在运行级别 3 和 5 启动,就需要在/etc/rc.d/rc3.d//etc/rc.d/rc5.d/中创建指向/etc/init.d/httpd的符号链接,如S80httpd(表示启动顺序为 80)。

2.2.1.2、/etc/systemd/system/
  1. 基于systemd系统,它不依赖于传统的运行级别概念systemd使用单元(unit)的方式来管理各种系统资源,包括服务。**在这个目录下的服务单元文件(.service)定义了服务的详细信息,如启动类型(有简单(simple)、分叉(forking)等多种类型)、依赖关系(通过AfterRequires等参数指定)、重启策略(如on - failure表示在失败时重启)等。systemd会根据这些单元文件的定义来启动和管理服务,并且可以并行启动多个没有依赖关系的服务,大大提高了系统启动速度。

  2. 例如,一个httpd.service文件在[Unit]部分可以定义After = network.target,表示这个服务在网络服务启动之后启动;在[Service]部分可以定义ExecStart = /usr/bin/httpd - f /etc/httpd.conf来指定服务启动的命令。

2.2.2配置文件格式和复杂度

2.2.2.1、/etc/init.d//usr/local/etc/rc.d

1)这里的服务脚本通常是 Shell 脚本格式,格式相对比较灵活,但也需要遵循一定的 Shell 脚本编写规范。编写这些脚本时,需要自己处理服务启动和停止的详细逻辑,包括进程的查找、信号的处理等。例如,在停止服务时,可能需要在脚本中使用kill命令来发送信号给服务进程,并且要考虑如何正确地终止进程。

2)以一个简单的/etc/init.d/myservice脚本为例,它可能包含如下内容:

         #!/bin/sh
         case "$1" in
           start)
             # 启动服务的代码,可能是启动一个可执行程序
             /usr/bin/myservice_executable &
             ;;
           stop)
             # 停止服务的代码,可能是查找并杀死服务进程
             killall myservice_executable
             ;;
           *)
             echo "Usage: $0 {start|stop}"
             exit 1
             ;;
         esac
         exit 0
2.2.2.2、/etc/systemd/system/

1)服务单元文件采用类似INI的格式,分为[Unit][Service][Install]**等几个部分。每个部分有特定的参数用于定义服务的不同属性。**这种格式更加规范,使得服务的配置信息更加清晰明了。并且systemd本身会处理很多底层的服务管理细节,减轻了服务配置文件编写者的负担。

2)例如,一个简单的httpd.service文件可能如下:

         [Unit]
         Description = Apache HTTP Server
         After = network.target
         [Service]
         Type = simple
         ExecStart = /usr/bin/httpd - f /etc/httpd.conf
         Restart = on - failure
         [Install]
         WantedBy = multi - user.target

2.2.3依赖关系处理方式

2.2.3.1、/etc/init.d//usr/local/etc/rc.d

处理服务之间的依赖关系相对复杂。通常需要在脚本中通过检查其他服务是否已经启动,或者通过在不同运行级别目录中设置符号链接的顺序来体现依赖关系。例如,如果服务A依赖于服务B,可能需要在服务A的脚本中添加代码来检查服务B的状态,或者确保服务B的启动符号链接在服务A之前。

2.2.3.2、/etc/systemd/system/

1)可以在服务单元文件的[Unit]部分方便地使用参数来定义服务的依赖关系。例如,使用After参数可以指定本服务在其他哪些服务之后启动,使用Requires参数可以明确表示本服务依赖于其他服务。systemd会根据这些定义自动处理服务的启动顺序,确保依赖的服务先启动。

2)例如,在一个database.service文件中可以定义Requires = network.service,表示数据库服务依赖于网络服务,systemd会在启动数据库服务之前先启动网络服务。