Linux tip: Register as a service and set it to boot

“This is the 30th day of my participation in the Gwen Challenge in November. See details: The Last Gwen Challenge in 2021”

Method 1. System V Init service

System V Init services are in the /etc/init.d/ directory. It’s actually a soft connection

The soft connection connects to /etc/rc.d/init.d/

Run Level

The Init process is the first user process after the system starts, so its PID (process number) is always 1. The first thing the init process does is read the value of initdefault ID in the inittab file in /etc/init. this value is called run-level. It determines the level at which the system will run after startup. The runlevel determines most of the behavior and purpose of system startup. This level ranges from 0 to 6 and has different functions. The different runlevels are defined as follows:

  • 0 – Downtime (never set initDefault to 0 or the system will never boot)
  • 1 – Single user mode
  • 2 – Multi-user, no NFS
  • 3 – Full multi-user mode (standard runlevel)
  • 4 – System reserved
  • 5 – X11 (x window)
  • 6 – Restart (never set initDefault to 6 or you will keep restarting)

Relationship between /etc/rc.d/ and /etc/rc.d/init.d

The script in /etc/rc.d/init.d is similar to the registry in Windows and is executed at startup time.

After deciding on the run level to boot the system, the /etc/rc.d/rc script is executed first. For each runlevel, there is a subdirectory in rc.d, rc0.d, rc1… . Rc6. D.

Each directory contains links to a part of the script to the init.d directory. For example, the services to be started at level 5 are placed in rc5.d, but the files in rc5.d are linked to the corresponding files in init.d, and the scripts in init.d actually work.

  1. Why do these link files have a Kxx or Sxx in front of them?
  • K indicates to stop (Kill) the service, which automatically adds the stop parameter to the script
  • S indicates that the Start service is enabled, and the Start parameter is automatically added to the script
  1. What about the numbers after the K and S?
  • Sorting is used to determine the order in which these scripts are executed, with smaller values being executed first and larger values being executed later
  • Many times this order of execution is important, such as when you need to configure the network interface to start the Apache service
  1. I accidentally noticed that the same service with S and K links to init.d are followed by the same script
  • S and K also pass the start and stop arguments to the script below init.d, respectively.
    • The /etc/rc.d/init.d/ XXX start command is executed when S is transmitted
    • /etc/rc.d/init.d/ XXX stop

practice

1. Create a script

vi /app/self-start/myApp.sh

The script defines how to run the program when it receives the parameters passed when the system starts up.

#! /bin/sh
# chkconfig: 2345 85 15
# description:ljw test auto_run
 
The first line tells the system which shell to use

## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
S80myApp = S80myApp = S80myApp = S80myApp = S80myApp = S80myApp

Chkconfig -add auto_run chkconfig -add auto_run chkconfig -add auto_run
### 85 A smaller number indicates a higher boot priority
### 15 A smaller number indicates a higher priority
# # # description description can be find in the boot log: cat/var/log/messages | grep LJW
# the program name
RUN_NAME="myApp"
 
# jar location
JAVA_OPTS=/app/self-start/$RUN_NAME.jar
LOG_OPTS=/app/self-start/$RUN_NAME-log.log

echo $JAVA_OPTS
echo $LOG_OPTS
 
# Start method
start() {

		Check whether it has been started
		isRun=`ps -ef | grep $JAVA_OPTS | grep -v grep  | awk '{print $2}'`
		if [ $isRun ]
		then
			echo "$RUN_NAME is running!! Do not operate"
		else
			nohup java -jar $JAVA_OPTS > $LOG_OPTS &
			echo "$RUN_NAME started success!"
		fi
      
}
 
# end method
stop() {
        echo "stopping $RUN_NAME ..."
        #### assignment = no space left, pit ah...
        aa=`ps -ef | grep $JAVA_OPTS | grep -v grep | grep -v stop | awk '{print $2}'`
        echo kill: $aa
        kill9 -$aa
}
 
case "The $1" in
        start)
            start
            ;;
        stop)
            stop
            ;;
        restart)
            stop
            start
            ;;
        *)
                echo "Userage: $0 {start|stop|restart}"
                exit 1
esac
Copy the code

2. Grant permissions to scripts and programs

chmod +x /app/self-start/myApp.sh

chmod +x /app/self-start/myApp.jar

3. Create a script soft link to the script in /etc/init. d

sudo ln -s /app/self-start/myApp.sh /etc/init.d/myApp

4. Add services to the system

chkconfig --add myApp

Check whether to add

chkconfig --list

5. Set automatic startup

chkconfig myApp on

6. Service commands

Open the service

service myApp start

Stop the service

service myApp stop

Restart the service

service myApp restart

7. View server restart logs

After the server restarts, you can restart the configured service. You can find the description of the configured service in the startup log.

cat /var/log/messages | grep ljw

Error: Service does not support chkconfig

Check to see if there are two complete lines at the beginning of the script:

# chkconfig: 2345 85 15
# description:ljw test auto_run
Copy the code

These two lines should not be missing before the script, otherwise the chkconfig command will not report an error.

This is a soft connection automatically generated by chkconfig according to script configuration: level 2345 are all S85: open state sort 85

If chkconfig is running and there is no problem with the script, I recommend that you create a file connection to the script directly under rc0.d to rc6.d.

Method 2. Systemd Service (recommended)

As a newcomer, Systemd is more powerful and supports more commands and parameters. Unit is the basic Unit of Systemd for task management

Directory where the Unit file is stored in Systemd

  1. /etc/systemd/system: system or user-defined configuration file
  2. /run/systemd/system: configuration file generated when the software is running
  3. /usr/lib/systemd/system: configuration file added during system or third-party software installation. (also lib/systemd/system; In Centos8, because the /lib directory has become a symbolic link to /usr/lib)
  • The Unit file is placed in one of the three specified system directories according to the Systemd convention
  • The three directories have priorities. The higher the priority, the higher the priority
  • If there are files with the same name in three directories, only the files in the directory with the highest priority will be used
  • By default, Systemd reads configuration files from the /etc/systemd/system/ directory. Most of the files stored in the directory are symbolic links to the /usr/lib/systemd/system/ directory
  • In /etc/systemd/system, symbolic links to the unit file in /usr/lib/systemd/system are usually placed instead of the unit file itself
# view all units
$ systemctl list-unit-files

View all units of Service
$ systemctl list-unit-files --type service

View all Timer units
$ systemctl list-unit-files --type timer
Copy the code

The type of unit

  • Service unit: system Service
  • Target Unit: A group of multiple units
  • Device Unit: hardware Device
  • Mount Unit: Mount point of a file system
  • Automount Unit: indicates an automatic mount point
  • Path Unit: file or Path
  • Scope Unit: External process not started by Systemd
  • Slice Unit: process group
  • Socket Unit: Indicates the Socket used for communication between processes
  • Swap Unit: Swap file
  • Timer Unit: indicates a Timer
  • Snapshot Unit: indicates the running status snapshot of Systemd Units created by the systemctl snapshot command

File format description of Service Unit

Unit of type service represents a background service process. Let’s go into detail on how to configure unit of service type.

Let’s start with a simple service configuration:

cat /usr/lib/systemd/system/firewalld.service

[Unit]
Description=firewalld - dynamic firewall daemon
Before=network-pre.target
Wants=network-pre.target
After=dbus.service
After=polkit.service
Conflicts=iptables.service ip6tables.service ebtables.service ipset.service
Documentation=man:firewalld(1)

[Service]
EnvironmentFile=-/etc/sysconfig/firewalld
ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS
ExecReload=/bin/kill -HUP $MAINPID
# supress to log debug and error output also to /var/log/messages
StandardOutput=null
StandardError=null
Type=dbus
BusName=org.fedoraproject.FirewallD1
KillMode=mixed

[Install]
WantedBy=multi-user.target
Alias=dbus-org.fedoraproject.FirewallD1.service

Copy the code

The configuration file name of the service type must end with.service.

Unit

The [Unit] block is usually the first block in a configuration file and defines metadata for a Unit and configures its relationship to other units, including Settings such as what service to start the Unit after.

  • Description: A short Description of the unit

  • Documentation: document address

  • Requires: The current Unit depends on other units. If they are not running, the current Unit will fail to start.

  • Wants: Other units that work with the current Unit. If they are not running, the current Unit will not fail to start.

  • BindsTo: Similar to Requires, it specifies a Unit that will stop running if it exits

  • Before: indicates that the service needs to be executed Before the XXX service is started

  • After: indicates that the service needs to be executed After the XXX service is started

  • Conflicts: The Unit specified here cannot run at the same time as the current Unit

  • Condition… : Conditions that must be met to run the current Unit. Otherwise, the Unit will not run

  • Assert… : Indicates the conditions that must be met when the Unit is running. Otherwise, a startup failure is reported

All startup Settings can be preceded by a conjunction sign (-) to indicate error suppression. That is, when an error occurs, the execution of other commands will not be affected.

For example, EnvironmentFile=-/etc/sysconfig/sshd (note the conjunction after the equal sign) means that the /etc/sysconfig/sshd file does not exist and does not throw an error.

Service

The [Service] block is used to configure services. Only units of Service type have this block.

For example, unit of the timer type should be [timer]; Unit of socket type should be [socket]; The unit of the Service type is [Service]. This project mainly specifies the script for starting the Service, the name of the environment configuration file, the way to restart the Service, and so on.

  • Type: defines the process behavior at startup. It has the following values
    • Type=simple: Default value. Execute the command specified by ExecStart to start the primary process. The process started by the ExecStart field is the primary process
    • Type=forking: Fork the child process from the parent. The parent process exits immediately and the child process continues to run as the main process of the service. This is the classic practice of traditional UNIX daemons. (Jar services use this)
    • Type=oneshot: a one-time process that Systemd waits for to complete before continuing to start other services
    • Type= Dbus: Similar to simple, but waits for the D-bus signal to start
    • Type=notify: After the current service is started, Systemd will be notified and continue
    • Type=idle: Similar to simple, but the service is not started until all other tasks are completed. One use is to keep the output of this service from mixing with the output of other services
  • User: Which User environment variable to use to run the service correctly
  • ExecStart: start the current service command: can’t accept the <, >, > >, |, & special characters, such as many bash syntax doesn’t support. So, to use these special characters, it is best to write directly into the script!
  • ExecStartPre: indicates the command to be executed before starting the current service
  • ExecStartPost: command to be executed after starting the current service
  • ExecReload: command executed when the current service is restarted
  • ExecStop: command to stop the current service
  • ExecStopPost: Stops the command executed after its service
  • RestartSec: indicates the number of seconds between automatic restart of the current service
  • Restart: defines the conditions under which Systemd automatically restarts the current service
    • No (default value) : the system will not restart after exiting
    • On-success: The system restarts only when the exit status code is 0
      • Normal exit: the exit code is “0”, or the process has received SIGHUP, SIGINT, SIGTERM, SIGPIPE and the exit code conforms to the setting of SuccessExitStatus=.
    • On-failure: Restarts when the exit status code is not 0, including being terminated by a signal or timed out
    • On-abnormal: The device restarts only when a signal terminates or times out
    • On-abort: Restarts only when an uncaught signal terminates
    • On-watchdog: The system restarts only when you exit the watchdog due to timeout
    • Always: No matter what the reason for quitting, always restart (When a process is due to systemd normal operation (e.g. systemctl stop | restart) and stops, the service will not be restarted. Even using kill -9 will restart the system)

  • TimeoutSec: Defines the number of seconds to wait before Systemd stops the current service
  • SuccessExitStatus: Define the additional “normal exit” status of the process, e.g., SuccessExitStatus=1 2 8 SIGKILL; Indicates that a process can be considered “normal exit” when its exit code is 1, 2, or 8, or when terminated by SIGKILL.
  • PrivateTmp: no use the PrivateTmp directory
  • KillMode: defines how Systemd stops the service. The value can be:
    • Control-group (default) : All child processes in the current control group are killed
    • Process: Kills only the main process
    • Mixed: The main process will receive the SIGTERM signal and the child process will receive the SIGKILL signal
    • None: No process is killed, only the stop command of the service is executed
  • Environment: Specifies the Environment variable. You can use it more than once
[Service]
# Client Env Vars
Environment=XXX_A=A
Environment=XXX_B=B
Copy the code
  • EnvironmentFile: Environment parameter file
    • 1. The script can save the following contents to the testenv file:
      • AAA_IPV4_ANCHOR_0=X.X.X.X
    • 2. Declare EnvironmentFile EnvironmentFile=/testenv
    • ExecStart=/ XXX xx${AAA_IPV4_ANCHOR_0}

Install

[Install] is usually the last block in the configuration file that defines how to boot and whether to boot at all. This section sets the target to which the unit is installed.

  • WantedBy: It has a value of one or more targets, and when the current Unit is activated (enable) the symbolic link is put into the /etc/systemd/system subdirectory with the Target name +. Wants suffix (weak dependency), i.e. the installation starts when the full contents of XXX are ready
  • RequiredBy: It takes one or more targets. When Unit is active, symbolic links are placed in subdirectories with the Target name +.required under /etc/systemd/system (strong dependency).
  • Alias: The current Alias that Unit can use to start
  • Also: Other units that will be activated at the same time when the current Unit is enabled

Systemd. service Chinese manual

The Service Unit practice

1. Create the Unit script in /etc/systemd/system/

View the group to which user root belongs and the member groups root

Create a service script: vi/etc/systemd/system/myService. Service

Note: Soft connection cannot be used here. Create the service script directly in this path. Because canceling the autostart command will delete the soft connection altogether. Then have to manually create soft connection to use, trouble.

Enter the following for the JAR service:

[Unit] Description=My Spring Boot Service After=syslog.target [Service] ##true: TMP share You can run the JPS command to view the Java process.false: private, can only use ps - ef | grep view # PrivateTmp =trueUser=root Group=root ## Shutting down and restarting Systemd will help me control, and configuration is also available. ExecStart=/app/self-start/start.sh ###1The above myApp script, configuration on, restart, Run the #ExecStart=/app/self-start/ myapp. sh start #ExecReload=/app/self-start/ myapp. sh restart command #ExecStop=/app/self-start/myApp.sh stop Restart=always #RestartPreventExitStatus=1

[Install] 
WantedBy=multi-user.target
Copy the code

Note:

  • PrivateTmp=true
    • When the service starts, it will generate something like this in/TMP / : / TMP/systemd – private – bceaa1ad35764ee2aea3cdd52fab89cd – myService. Service – rVFD0q/TMP/hsperfdata_root folder, Temporary file for myService. Pid to store thread – private, can only operate on its own account
    • The JPS command is used to query shared files in the/TMP/directory. All processes with PrivateTmp=true are invisible to this command. Please use: ps - ef | grep Java
  • PrivateTmp=false
    • When the service is started, a shared file is generated in the/TMP/directory, which stores the PID of the thread. – All users have read and write permissions.
  • Multi-user. Target: Wait until all the contents of the multi-user system are ready to install and start

2. Create a startup script

vi /app/self-start/start.sh

Start the service and save the pid of the process to a custom file /app/self-start/ myapp.pid

#! /bin/sh
nohup /usr/bin/java -jar /app/self-start/myApp.jar > /app/self-start/myApp.log & echo $! >/app/self-start/myApp.pid
Copy the code

3. Grant script and program permissions

chmod +x /app/self-start/start.sh

chmod +x /app/self-start/myApp.jar

4. Reload all modified Unit files

systemctl daemon-reload

5. View the configuration

Can see the configuration proof service file no syntax errors, logic and environment errors can not be found, to see the startup log

systemctl show -p ExecStart myService

6. Start the service and configure startup

Start: sudo systemctl start myService

Status: sudo Systemctl status myService

Stop: sudo systemctl stop myService

Restart: sudo systemctl restart myService

Run the sudo systemctl enable myService command to start the system

To disable the startup, run the sudo systemctl disable myService command

Run journalctl -u myservice.service to view service startup logs

The Timer Unit practice

Detailed configuration of the Timer Unit

The Unit of the Timer type is mainly used to perform scheduled tasks and may replace the CRon service.

Unlike unit for the service type, the main part of the Timer Unit configuration file is [timer]. Here are the main configuration items:

[Timer]

  • OnActiveSec: Specifies the time when tasks start to be executed after the timer takes effect
  • OnBootSec: Specifies the time when tasks are executed after the system starts
  • OnStartupSec: Specifies the time when the Systemd process starts to execute tasks
  • OnUnitActiveSec: How long has the unit waited to execute again since its last execution
  • OnUnitInactiveSec: Indicates the time after the timer was turned off for the last time
  • OnCalendar: Execute based on absolute time, not relative time
  • AccuracySec: If the task must be delayed for various reasons, the maximum number of seconds that the task can be delayed is 60 seconds by default
  • Unit: The actual task to be executed, default is with the same name.serviceSuffixed unit
  • Persistent: If this field is set, the corresponding unit will be automatically executed even if the timer is not started
  • WakeSystem: Specifies whether to wake up the system automatically if the system is hibernated

1. Create a backup script

vi /app/self-start/backup.sh

#! /bin/bash
mydate()
{
        date "+%Y%m%d%H%M%S"
}
backupdate=$(mydate)
Package the folders that need to be backed up
tar -zcPf /app/self-start/bk.${backupdate}.tar.gz /app/self-start/bk
Copy the code

2. Grant the execution permission

sudo chmod +x /app/self-start/backup.sh

3. Service Unit configuration file

vi /etc/systemd/system/backup.service

[Unit]
Description=my backup learn dir service

[Service]
User=root
Group=root
Type=simple
Execute the script
ExecStart=/app/self-start/backup.sh

[Install]
WantedBy=multi-user.target
Copy the code

4. Configure the timing service

vi /etc/systemd/system/backup.timer

[Unit]
Description=my backup learn dir timer

[Timer]
Execute every 15 minutes
#OnCalendar=*:0/15
# Execute once on the 26th of each month at 0:30am
#OnCalendar=*-*-26 00:30:00

Start the timer 1 minute after the interval of 1 second
OnBootSec=1min
OnUnitActiveSec=30s

Persistent=true
Configure the service to be timed
Unit=backup.service

[Install]
WantedBy=multi-user.target
Copy the code

5. Related commands

Refresh the configuration: sudo systemctl daemon-reload

Run the sudo systemctl start backup.service command to start the backup service

Run the sudo systemctl start backup.timer command to start the timing service

Run the sudo systemctl enable backup.service command to start the backup service upon system startup

Run the sudo systemctl enable backup.timer command to start the timing service upon startup

Run the sudo systemctl status backup.service command to query the backup service status

Check the status of the timer service: sudo systemctl status backup.timer

View the entire log :sudo journalctl

Sudo journalctl -u backup.timer: sudo journalctl -u backup

Run sudo journalctl -u backup to view backup.timer and backup.service logs

Start at the end to view the latest log :sudo journalctl -f

Journalctl -f -u backup.timer: Journalctl -f -u backup.timer: journalctl -f -u backup.timer

Method 3: Start the configuration directly

In addition to registering the service above and setting it to boot up, there is another way to configure boot up directly.

practice

1. Create a script

vi /app/self-start/directStart.sh

#! /bin/bash

Can wait 20 seconds before running. Wait for other services or environments
##sleep 10
## this is a test command
echo "Turned on" > /app/self-start/a.txt
## Java command using absolute path. The environment may not be ready for server restart
nohup /usr/bin/java -jar /app/self-start/myApp.jar > /app/self-start/nohup.out 2>&1 &
Copy the code

2. Grant permissions to scripts and programs

chmod +x /app/self-start/myApp.jar

chmod +x /app/self-start/directStart.sh

/etc/rc.local does not have execution permission by default.

chmod +x /etc/rc.local

3. Modify the startup file /etc/rc.local

It is better to write the absolute command path /bin/bash completely

/bin/bash /app/self-start/directStart.sh 
Copy the code

4. Check whether the configuration is normal

Whether it is possible to run the test manually.

bash /etc/rc.local

5. Restart the test

reboot

The problem

  • In Linux, to add services that automatically run with system startup, you only need to add them in the /etc/rc.local script file.

  • However, there is a problem that the script manual test can run properly. The Java command in /etc/rc.local does not run properly or fails to execute. The touch command succeeds. The commands without paths in the script are as follows:

    • nohup java -jar /app/self-start/myApp.jar > /app/self-start/nohup.out 2>&1 &
  • An error occurs when the system restarts and these commands cannot be executed properly. The reasons:

    • The PATH environment variable is not fully initialized when the rc.local script is executed. The PATH environment variable must be added to the PATH environment variable after the /etc/profile command is executed.
  • Some commands need to use absolute paths in order to execute them on startup

[root@k8s2 self-start]# which java
/usr/bin/java
Copy the code
  • nohup /usr/bin/java -jar /app/self-start/myApp.jar > /app/self-start/nohup.out 2>&1 &
  • This is a big disadvantage compared to registering as a service, and you can’t control how fine-tuned the script startup time is and what environment is required.