ubuntu · 2022-08-31 0

ubuntu 服务管理 init.d、service 和 systemctl

脚本

1.创建脚本

创建脚本 print.sh,每 5s 打印信息

#!/bin/bash

max_iterations=1000

for ((i=1; i<=max_iterations; i++))
do
    echo "Iteration $i"
    sleep 5
done

2.bash 运行脚本,查看进程

root@node-pc:~# /root/print.sh
root@node-pc:~# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:52 ?        00:00:00 /sbin/init
root         836       1  0 09:53 tty1     00:00:00 /bin/login -p --
root        1036     836  0 09:53 tty1     00:00:00 -bash
root        1060    1036  0 09:53 tty1     00:00:00 /bin/bash /root/print.sh
root        1129    1060  0 09:54 tty1     00:00:00 sleep 5

3.nohup 运行脚本,查看进程

root@node-pc:~# nohup /root/print.sh > /root/output.log 2>&1 &
[1] 1170
root@node-pc:~# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:52 ?        00:00:00 /sbin/init
root         836       1  0 09:53 tty1     00:00:00 /bin/login -p --
root        1036     836  0 09:53 tty1     00:00:00 -bash
root        1170    1036  0 09:57 tty1     00:00:00 /bin/bash /root/print.sh
root        1179    1170  0 09:58 tty1     00:00:00 sleep 5

一、/etc/init.d

在较新的 Ubuntu 版本(如 Ubuntu 18.04)中,使用 systemd 替代了旧的 /etc/init.d 系统启动脚本。

下面使用旧的 /etc/init.d 方式设置服务。

1.创建服务脚本

创建脚本 /etc/init.d/my-service.sh,内容如下:

#!/bin/bash

### BEGIN INIT INFO
# Provides:          my-ss
# Required-Start:    $local_fs $network
# Required-Stop:     $local_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start my ss at boot time
# Description:       My service does <description>
### END INIT INFO

case "$1" in
  start)
    echo "start ..."
    nohup /root/print.sh > /root/output.log 2>&1 &
    ;;
  stop)
    echo "stop ..."
    ;;
  restart)
    echo "restart ..."
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
    ;;
esac

exit 0

在 SysVinit 初始化脚本中,Default-Start 和 Default-Stop 这两行注释是特别重要的

Default-Start 字段列出了服务在系统启动时应该自动启动的运行级别,Default-Start: 2 3 4 5,这表示服务应该在运行级别2、3、4和5下自动启动。在这些运行级别中,系统初始化时会查找并执行以S开头的符号链接,这些链接指向了你的服务脚本,从而启动服务。

Default-Stop 字段指定了服务在哪些运行级别下应该自动停,Default-Stop: 0 1 6,这表示服务应该在运行级别0(关机)、1(单用户模式)和6(重启)下自动停止。在这些运行级别中,系统会查找并执行以K开头的符号链接,这些链接同样指向了你的服务脚本,但是会执行停止服务的命令。

设置脚本执行权限:

chmod +x /etc/init.d/my-service.sh

2.启动服务

虽然可以使用 /etc/init.d 方式来启动服务,但建议尽可能使用 systemd 来管理自启动服务。

root@node-pc:~# /etc/init.d/my-service.sh start

查看进程

root@node-pc:~# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:52 ?        00:00:00 /sbin/init
root        1237       1  0 10:01 tty1     00:00:00 /bin/bash /root/print.sh
root        1247    1237  0 10:01 tty1     00:00:00 sleep 5

3.开机自启动服务

  • update-rc.d <basename> defaults 增加服务
  • update-rc.d -f <basename> remove 删除服务

update-rc.d 就是通过管理 /etc/init.d 目录下的脚本文件来管理系统启动时的计划任务的,例如 ssh 服务、Apache 服务、MySQL 服务等。

使用 update-rc.d my-service.sh defaults 增加一个服务,可以看到在 /etc/rc5.d/ 有个 以S开头的符号链接,这表示这个服务会开机启动

root@node-pc:~# ls -lh /etc/rc5.d/
root@node-pc:~# update-rc.d my-service.sh defaults
root@node-pc:~# ls -lh /etc/rc5.d/
lrwxrwxrwx 1 root root 23 Jul 14 10:04 S01my-service.sh -> ../init.d/my-service.sh

使用 update-rc.d -f my-service.sh remove 删除一个服务,可以看到在 /etc/rc5.d/ 已无对应的符号链接

root@node-pc:~# ls -lh /etc/rc5.d/
lrwxrwxrwx 1 root root 23 Jul 14 10:04 S01my-service.sh -> ../init.d/my-service.sh
root@node-pc:~# update-rc.d -f my-service.sh remove
root@node-pc:~# ls -lh /etc/rc5.d/

重启后,查看进程:

UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 10:05 ?        00:00:00 /sbin/init
root         765       1  0 10:05 ?        00:00:00 /bin/bash /root/print.sh
root        1033     765  0 10:06 ?        00:00:00 sleep 5

二、service

service 命令其实是去 /etc/init.d 目录下,去执行相关程序

  • service <service_name> [start | stop |restart |reload |stauts]
  • service --status-all 查看所有服务

当脚本在 /etc/init.d/ 下,刷新服务后,service 会看到服务状态

root@node-pc:~# systemctl daemon-reload
root@node-pc:~# service my-service status
○ my-service.service - LSB: Start my ss at boot time
     Loaded: loaded (/etc/init.d/my-service.sh; generated)
     Active: inactive (dead)
       Docs: man:systemd-sysv-generator(8)
root@node-pc:~# service --status-all
 [ ? ]  my-service.sh

使用 serice 命令启动后,可以看到服务状态

root@node-pc:~# service my-service start
root@node-pc:~# service my-service status
● my-service.service - LSB: Start my ss at boot time
     Loaded: loaded (/etc/init.d/my-service.sh; generated)
     Active: active (running) since Sun 2024-07-14 10:11:21 UTC; 2s ago
       Docs: man:systemd-sysv-generator(8)
    Process: 1232 ExecStart=/etc/init.d/my-service.sh start (code=exited, status=0/SUCCESS)
      Tasks: 2 (limit: 4513)
     Memory: 636.0K
        CPU: 2ms
     CGroup: /system.slice/my-service.service
             ├─1233 /bin/bash /root/print.sh
             └─1234 sleep 5

Jul 14 10:11:21 node-pc systemd[1]: Starting LSB: Start my ss at boot time...
Jul 14 10:11:21 node-pc my-service.sh[1232]: start ...
Jul 14 10:11:21 node-pc systemd[1]: Started LSB: Start my ss at boot time.
root@node-pc:~# service my-service status
● my-service.service - LSB: Start my ss at boot time
     Loaded: loaded (/etc/init.d/my-service.sh; generated)
     Active: active (running) since Sun 2024-07-14 10:11:21 UTC; 1min 9s ago
       Docs: man:systemd-sysv-generator(8)
    Process: 1232 ExecStart=/etc/init.d/my-service.sh start (code=exited, status=0/SUCCESS)
      Tasks: 2 (limit: 4513)
     Memory: 636.0K
        CPU: 44ms
     CGroup: /system.slice/my-service.service
             ├─1233 /bin/bash /root/print.sh
             └─1256 sleep 5

Jul 14 10:11:21 node-pc systemd[1]: Starting LSB: Start my ss at boot time...
Jul 14 10:11:21 node-pc my-service.sh[1232]: start ...
Jul 14 10:11:21 node-pc systemd[1]: Started LSB: Start my ss at boot time.

三、systemctl

systemd 是 Linux 系统最新的初始化系统(init),作用是提高系统的启动速度,尽可能启动较少的进程,尽可能更多进程并发启动。

systemd 对应的进程管理命令是 systemctl

systemctl 命令管理 systemd 的资源 Unit,systemd 的 Unit 放在目录 /etc/systemd/system,systemctl 也会去 /etc/init.d 目录下,查看,执行相关程序

1.创建服务脚本

创建脚本 /etc/systemd/system/myapp.service,内容如下:

[Unit]
Description=myapp service

[Service]
Type=simple
WorkingDirectory=/root
ExecStart=/bin/bash -c "/root/print.sh > /root/output.log 2>&1"

[Install]
WantedBy=multi-user.target

2.启动服务

如果 /etc/systemd/system/myapp.service 有过修改,需要进行更新,执行 systemctl daemon-reload

查看服务是否被正确识别,执行 systemctl list-unit-files | grep myapp

  • systemctl [start | stop |restart |reload |stauts] <service_name>
root@node-pc:~# systemctl start myapp.service
root@node-pc:~# systemctl status myapp.service
● myapp.service - myapp service
     Loaded: loaded (/etc/systemd/system/myapp.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2024-07-14 10:29:45 UTC; 13s ago
   Main PID: 1051 (bash)
      Tasks: 3 (limit: 4513)
     Memory: 896.0K
        CPU: 8ms
     CGroup: /system.slice/myapp.service
             ├─1051 /bin/bash -c "/root/print.sh > /root/output.log 2>&1"
             ├─1052 /bin/bash /root/print.sh
             └─1057 sleep 5

Jul 14 10:29:45 node-pc systemd[1]: Started myapp service.

查看进程:

UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 10:23 ?        00:00:00 /sbin/init
root        1051       1  0 10:29 ?        00:00:00 /bin/bash -c /root/print.sh > /root/output.log 2>&1
root        1052    1051  0 10:29 ?        00:00:00 /bin/bash /root/print.sh
root        1087    1052  0 10:31 ?        00:00:00 sleep 5

3.创建服务脚本

可使用 StandardOutput 指定日志文件

root@node-pc:~# cat /etc/systemd/system/myapp.service
[Unit]
Description=myapp service

[Service]
Type=simple
WorkingDirectory=/root
ExecStart=/root/print.sh
StandardOutput=file:/root/output.log

[Install]
WantedBy=multi-user.target

4.启动服务

root@node-pc:~# systemctl start myapp.service
root@node-pc:~# systemctl status myapp.service
● myapp.service - myapp service
     Loaded: loaded (/etc/systemd/system/myapp.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2024-07-14 10:44:10 UTC; 2s ago
   Main PID: 1051 (print.sh)
      Tasks: 2 (limit: 4513)
     Memory: 572.0K
        CPU: 1ms
     CGroup: /system.slice/myapp.service
             ├─1051 /bin/bash /root/print.sh
             └─1052 sleep 5

Jul 14 10:44:10 node-pc systemd[1]: Started myapp service.

查看进程:

root           1       0  0 10:40 ?        00:00:00 /sbin/init
root        1051       1  0 10:44 ?        00:00:00 /bin/bash /root/print.sh
root        1106    1051  0 10:47 ?        00:00:00 sleep 5

5.自启动服务

  • systemctl enable myapp.service 启动自启动服务
  • systemctl disable myapp.service 取消自启动服务
  • systemctl is-enabled myapp.service 查看服务是否开机启动

四、journalctl

journalctl 是一个非常强大的工具,用于查看和管理由 systemd 的 journald 服务收集的系统日志。

journalctl并不直接读取传统的文本日志文件,而是访问由systemd的journald守护进程维护的日志存储。默认情况下,journald的日志文件存储在/var/log/journal/目录下。

参数:

  • -e 或 --cursor:这个选项滚动日志输出直到显示最新的日志条目,然后保持在屏幕底部,继续接收新的日志消息。这类似于 tail -f 命令的功能,用于实时查看日志文件的新增内容
  • -u 或 --unit:这个选项后面跟的是服务单元的名称,告诉 journalctl 你想要查看哪个服务的日志
journalctl -eu <service-unit>