Linux系统应用--systemd服务(一)
文章摘要:
本文主要描述了systemd服务的应用,从 CentOS 7.x 以后,Red Hat 系列的发行版开始采用systemd的服服务管理模式,该模式支持并行启动,可以加快系统的启动速度。
操作系统: raspbian/debian
硬件平台: 树莓派
服务分类:
.service
一般服务类型,最常见的类型,主要是系统服务,包括服务器本身所需要的本地服务以及网络服务都是,比较经常被使用到的服务大多是这种类型。
.socket
内部程序数据交换的插槽(socket)服务,主要是 IPC (Inter-process communication) 的传输讯息插槽文件 (socket file) 功能。这种类型的服务通常在监控讯息传递的插槽文件,当有透过此插槽文件传递讯息来说要链接服务时,就依据当时的状态将该用户的要求传送到对应的服务,若服务尚未启动,则启动该服务后再传送用户的要求。
使用 socket 类型的服务一般是比较不会被经常用到的服务,因此在开机时通常会稍微延迟启动的时间 。一般用于本地服务比较多,例如我们的图形界面很多的软件都是透过 socket 来进行本机程序数据交换的行为。与早期的 xinetd 这个 super daemon 有部份的相似。
.target
执行环境类型:执行一系列的.service 或.socket 之类的服务的集合,例如 multi-user.target。
.mount
.automount
文件系统挂载相关的服务,文件系统的自动挂载等与文件系统相关性较高的程序管理。
.path
侦测特定文件或目录类型,某些服务需要侦测某些特定的目录来提供队列服务,例如最常见的打印服务,就是透过侦测打印队列目录来启动打印功能! 这时就得要 .path 的服务类型支持了!
.timer
循环执行的服务,有点类似 anacrontab 。
systemctl command 主要有:
start : 立刻启动服务
stop : 立刻关闭服务
restart : 重启服务,相当于先start,再stop
reload : 重载配置文件,让设定生效(不关闭服务)
enable : 设定开机时自动启动
disable : 取消开机时自动启动
status : 显示服务状态,会列出有没有正在执行、开机预设执行否、登录等信息等
is-active : 显示服务是否正在运行
is-enabled: 显示是否设定了开机启动
mask :注销服务
unmask :取消注销状态
其他命令:
列出已安装的服务
systemctl list-unit-files
配置文件各字段说明:
[Unit]
Description
使用 systemctl list-units 时命令时,会输出给管理员看的简易说明,使用 systemctl status 输出的此服务的说明。
Documentation
帮助文档
After
说明此服务是在哪个服务启动之后才启动的,仅是说明服务启动的顺序而已,并没有强制要求。
Before
与 After 的意义相反,是在什么服务启动前最好启动这个服务。仅是规范服务启动的顺序并非强制要求。
Requires
明确的定义此服务需要在哪个服务进程启动后才能够启动,如果在此项设定的前导服务没有启动,那么该服务就不会被启动。
Wants
与 Requires 刚好相反,规范的是这个服务之后最好还要启动什么服务,但Wants后面接的服务如果没有启动,不会影响到这个 服务本身!
Conflicts
冲突的服务,项目后面接的服务如果有启动,那么服务就不能启动。
[Service]
Type
服务启动的方式,对ExecStart有影响
simple | 默认值,主要由 ExecStart 接的指令串来启动,启动后常驻于内存中。 |
forking | 由 ExecStart 启动的程序透过 spawns 延伸出其他子程序来作为主要服务。原生的父程序在启动结束后就会终止运作。 传统的 unit 服务大多属于这种项目,例如 httpd服务,当 httpd 的程序因为运作过久因此即将终结了,则 systemd 会再重新生出另一个子程序持续运作后,再将父程序删除。 |
oneshot | 与 simple 类似,不过在工作完毕后就结束了,不会常驻在内存中。 |
dbus | 与 simple 类似,必须要在取得一个 D-Bus 的名称后,才会继续运作,因此设定这个项目时,通常也要设定BusName。 |
idle | 与 simple 类似,必须要所有的工作都顺利执行完毕后才会执行。通常是开机到最后才执行即可的服务。 |
EnvironmentFile
指定启动脚本的环境配置文件,Environment后面可接多个不同的 Shell 变量来设定。
ExecStart
启动服务要执行的命令或脚本,可以使用 ExecStartPre (之前)以及 ExecStartPost (之后)两个设定项目来在实际启动服务前,进行额外的指令行为,指令串仅接受『指令 参数 参数...』的格式,不能接受 <, >, >>, |, & 等特殊字符。若要支持比较完整的 bash 语法需要指定Type=oneshot。
ExecStop
关闭服务时所进行的指令。
ExecReload
reload时执行的指令
Restart
Restart=1 时,服务终止后,会再次的启动此服务。
RemainAfterExit
RemainAfterExit=1 时,则当所属的所有程序都终止之后,此服务会再尝试启动。主要与Type=oneshot的服务配合。
TimeoutSec
服务在启动或者是关闭时,因为某些缘故导致无法顺利『正常启动或正常结束』的情况下,进行『强制结束』的超时时间,单位为(毫)秒。
KillMode
process - 服务终止时,只会终止 KillMode 主要的程序 (ExecStart 接的后面那串指令)
control-group - 由此服务所产生的其他control-group的程序,也都会被关闭。
none - 没有程序会被关闭。
RestartSec
服务被关闭后,再重新启动需经等待的时间 ,默认值为100(毫秒)。
[Install]
WantedBy
这个设定后面接的大部分是 *.target, 表示这个服务是附挂在哪一个target底下的,一般来说,大多的服务性质的服务都是附挂在 multi-user.target 底下。
Also
当服务被 enable时,Also 后面接的服务需要(手动)enable。
Alias
别名通过systemctl enable命令操作时,会建立一个别名的软链接。
例如multi-user.target的别名设定为default.target时,就会建立/etc/systemd/system/default.target指向/usr/lib/systemd/system/multi-user.target。
几个重要的目录
/etc/systemd/system - 基本上都是一些软连接,通过管理命令连接的,一般不要手动添加或者删除
/lib/systemd/system - 基本上都在这里了(新建,删除也在这里了)
/usr/lib/systemd/system - 使能的开机自启的服务(硬连接),调用enable/disable命令时创建/删除.
Linux系统应用--imx8m搭建vnc服务
操作系统: Ubuntu18.04 xfce4桌面系统
硬件平台:imx8m
安装xrdp
# sudo apt-get install xrdp
配置xfce4
# echo "xfce4-session">~/.xsession
修改/etc/xrdp/startwm.sh文件,在./etc/X11/Xsession前一行插入
xfce4-session
重启xrdp
# sudo service xrdp restart
安装vnc4server
# apt-get install vnc4server
设置vncserver的密码
# vncpasswd
启动vnc4server
# vnc4server
如果启动失败,日志提示:
mesg: ttyname 失败: 对设备不适当的 ioctl 操作
root用户修改/root/.profile文件,将/root/.profile文件中的mesg n替换成:
tty -s && mesg n
以下错误不用理会:不影响使用
error opening security policy file /etc/X11/xserver/SecurityPolicy
Could not init font path element /usr/X11R6/lib/X11/fonts/Type1/, removing from list!
Could not init font path element /usr/X11R6/lib/X11/fonts/Speedo/, removing from list!
Could not init font path element /usr/X11R6/lib/X11/fonts/misc/, removing from list!
Could not init font path element /usr/X11R6/lib/X11/fonts/75dpi/, removing from list!
Could not init font path element /usr/X11R6/lib/X11/fonts/100dpi/, removing from list!
安装tightvncserver软件:
apt-get install tightvncserver
设置密码: 可设置无操作权限的密码
# vncpasswd
Password:
Verify:
Would you like to enter a view-only password (y/n)? y
Password:
Verify:
启动服务:
# vncserver
New 'X' desktop is vnvn:1
Starting applications specified in /etc/X11/Xvnc-session
Log file is /root/.vnc/vnvn:1.log
关闭服务:
# vncserver -kill :1
树莓派笔记--切换声音通道
文章摘要:本文主要描述了如何修改树莓派默认声音输出通道,方法是修改用户家目录下的.asoundrc配置文件即可,主要区别在于 pcm.output字段的不同。
耳机通道输出:
#Analog
pcm.!default {
type asym
playback.pcm {
type plug
slave.pcm "output"
}
capture.pcm {
type plug
slave.pcm "input"
}
}
pcm.output {
type hw
card 1
}
ctl.!default {
type hw
card 1
}
HDMI通道输出:主要区别在card 0
pcm.!default {
type asym
playback.pcm {
type plug
slave.pcm "output"
}
capture.pcm {
type plug
slave.pcm "input"
}
}
pcm.output {
type hw
card 0
}
ctl.!default {
type hw
card 0
}
蓝牙耳机通道输出:
# 这一项目貌似大家都一样
pcm.!default {
type asym
playback.pcm {
type plug
slave.pcm "output"
}
capture.pcm {
type plug
slave.pcm "input"
}
}
# 声音输出设备
pcm.output {
# 类型为蓝牙音频
type bluealsa
# 设备为蓝牙音箱的MAC地址
device "FC:58:FA:E2:E4:3C"
# 配置文件
profile "a2dp"
}
# 声音输入设备(树莓派硬件上无输入通道,HDMI也不支持输入)
# 所以只有蓝牙耳机的配置文件才有输入通道
pcm.input {
type bluealsa
device "FC:58:FA:E2:E4:3C"
profile "sco"
}
ctl.!default {
type bluealsa
}
配置为蓝牙通道后,系统开机后或者蓝牙耳机开机时会自动连接。
Linux系统应用--CPU内存硬盘使用率
测试系统: Debian
TOP命令: -n 表示只刷新一次
$ top -n 1
top - 16:36:38 up 1:06, 3 users, load average: 1.95, 1.49, 1.42
Tasks: 180 total, 2 running, 178 sleeping, 0 stopped, 0 zombie
%Cpu(s): 22.9 us, 5.7 sy, 0.0 ni, 71.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 3854.5 total, 2304.4 free, 832.9 used, 717.1 buff/cache
MiB Swap: 100.0 total, 100.0 free, 0.0 used. 2706.4 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1065 root 20 0 328880 96868 64248 R 81.2 2.5 64:45.65 python3
671 root 20 0 142680 46616 31008 S 6.2 1.2 1:07.32 Xorg
6383 pi 20 0 10636 2976 2568 R 6.2 0.1 0:00.03 top
1 root 20 0 32712 8136 6532 S 0.0 0.2 0:04.94 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp
8 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq
9 root 20 0 0 0 0 S 0.0 0.0 0:00.34 ksoftirqd/0
其中第3行 %Cpu(s)表示CPU的使用情况
us - 表示用户空间程序的cpu使用率(user)
sy:表示系统空间的cpu使用率,主要是内核程序 (system)。
ni:表示用户空间且通过nice调度过的程序的cpu使用率。
id:空闲cpu(Idel)
wa:cpu运行时在等待io的时间
hi:cpu处理硬中断的数量
si:cpu处理软中断的数量
st:被虚拟机占用的cpu
71.4 id,表示空闲CPU,即CPU未使用率,100%-71.4%=28.6%,则系统的cpu使用率为28.6%。
其中第4行MiB Mem表示内存占用情况
free命令:
$ free
total used free shared buff/cache available
Mem: 3946964 851752 2360860 198248 734352 2773204
Swap: 102396 0 102396
打印空闲内存数量:
$ free -m | awk '/Mem/ {print $4}'
2304
-m表示以MB为单位,-G表示以GB为单位
查看磁盘使用情况:
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 19G 6.0G 12G 34% /
/dev/sdb1 20G 4.3G 15G 23% /opt
打印sda1的占用率:
$ df -h | awk '/sda1/ {print $5}'
34%
-h表示采用合适的单位(由于磁盘比较大,经常以GB为单位,以字节计时,数值太大)
基于python的脚本: 实际上仍按上述命令实现
#!/usr/bin/env python3
import os
# 获取CPU温度(仅树莓派支持)
def getCPUtemperature():
res = os.popen('vcgencmd measure_temp').readline()
return(res.replace("temp=","").replace("'C\n",""))
# 获取内存使用情况信息:
def getRAMinfo():
p = os.popen('free -m')
i = 0
while 1:
i = i + 1
line = p.readline()
if i==2:
return(line.split()[1:4])
# 获取CPU使用情况
def getCPUuse():
return(str(os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip()))
# 获取磁盘使用情况
def getDiskSpace():
p =os.popen("df -h /")
i = 0
while 1:
i =i + 1
line =p.readline()
if i==2:
return(line.split()[1:5])
#--------------------------------------------------------------
CPU_temp=getCPUtemperature()
CPU_usage=getCPUuse()
RAM_stats = getRAMinfo()
#RAM_total = round(int(RAM_stats[0]),1)
#RAM_used = round(int(RAM_stats[1]),1)
#RAM_free = round(int(RAM_stats[2]),1)
RAM_total = RAM_stats[0]
RAM_used = RAM_stats[1]
RAM_free = RAM_stats[2]
DISK_stats = getDiskSpace()
DISK_total = DISK_stats[0]
DISK_used = DISK_stats[1]
DISK_perc = DISK_stats[3]
if __name__ =='__main__':
print('CPU Temp = '+CPU_temp)
print('CPU Use = '+CPU_usage)
print('RAM Total = '+str(RAM_total) +'MB')
print('RAM Used = '+str(RAM_used) +'MB')
print('RAM Free = '+str(RAM_free) +'MB')
print('DISK Total = '+str(DISK_total)+'B')
print('DISK Used = '+str(DISK_used) +'B')
print('DISK Usage = '+str(DISK_perc))
基于C语言的方法:
#include <stdio.h>
#include <string.h>
#define CPU_IDEL_CMD "top -n 1 | awk '/Cpu/ {print $8}'"
#define MEM_FREE_CMD "free -m | awk '/Mem/ {print $4}'"
int main(int argc, char *argv[])
{
FILE* fp;
char buff[100];
fp = popen(MEM_FREE_CMD,"r");
bzero(buff,100);
fread(buff, 1, 50, fp);
printf("%s", buff);
fclose(fp);
return 0;
}