进程
进程是一个在系统中运行的程序
进程是已启动的可执行程序的运行实例,进程有以下组成部分
- 已分配内存的地址空间
- 安全属性,包括所有权凭据和特权
- 进程代码的一个或多个执行线程
- 进程状态
程序:二进制文件,静态/bin/date
,/usr/sbin/httpd
,/usr/sbin/sshd
,/usr/local/nginx/sbin/ngix
进程:是程序运行的过程,动态,有生命周期及运行状态
进程类型
守护进程:在系统引导过程中启动的进程,跟终端无关的进程
前台进程:跟终端相关,通过终端启动的进程
进程的生命周期
父进程复制自己的地址空间(fork)创建一个新的(子)进程结构。每个新进程分配一个唯一的进程ID(PID),满足跟踪安全性之需。PID和父进程ID(PPID)是子进程环境的元素,任何进程都可以创建子进程,所有进程都是第一个系统进程的后代。
systemd简介
首先 systmed 是一个用户空间的程序,属于应用程序,不属于 Linux 内核范畴。Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit(这个是centos6中的初始化系统)固有的缺点,提高系统的启动速度。
Linux内核加载启动后,用户空间的第一个进程就是初始化进程,这个程序的物理文件约定位于/sbin/init
,当然也可以通过传递内核参数来让内核启动指定的程序。这个进程的特点是进程号为1,代表第一个运行的用户空间进程。不同发行版采用了不同的启动程序,主要有以下几种主流选择:
- 以 Ubuntu 为代表的 Linux 发行版采用 upstart
- centos7.0 版本之前的 System V init
- centos7.0 版本的 systemd
centos7上所有的进程都是systemd的后代,systemd的功能繁多,不仅用来管理服务,还可以管理挂载点,定义定时任务等。这些工作都是由编辑相应的配置单元文件完成的。
systemd unit 类型
systemd需要管理的功能比较多,所以支持的配置单元类型也比较繁多,我们在日常使用Linux的过程中对系统服务的管理最多,所以我们主要了解一下service
类型即可,其他类型作为一个了解,下面列举出所有类型详细的解释。
单元类型 | 文件格式 | 描述 |
---|---|---|
Service unit | .service | 服务类 |
Target unit | .target | 一个 unit 服务组,用于模拟实现运行级别 |
Automount unit | .automount | 文件系统自动挂载点 |
Device unit | .device | 内核识别的设备文件 |
Mount unit | .mount | 文件系统挂载点 |
Path unit | .path | 文件或目录 |
Scope unit | .scope | 外部创建的进程 |
Slice unit | .slice | A group of hierarchically organized units that manage system processes. |
Snapshot unit | .snapshot | 系统快照 |
Socket unit | .socket | 套接字 |
Swap unit | .swap | 标识 swap 设备 |
Timer unit | .timer | systemd 的计时器 |
unit 文件保存位置
我们目前了解到文件所在的位置即可,关于文件内部的格式与如何修改这些文件,我们会在后续的服务搭建过程中细讲。
目录 | 描述 |
---|---|
/usr/lib/systemd/system/ | RPM 包安装时分发的 unit 文件 |
/run/systemd/system/ | systemd 运行时创建的文件 |
/etc/systemd/system/ | systemctl enable 创建的 unit 文件 |
管理系统服务
systemd 的主要命令行工具是systemctl
systemctl [选项...] {命令} ...
systemctl常用命令
这边列举出来的命令会在后面的学习过程中经常用到,所以大家只要对本部分中系统管理的命令合集有一个影响即可。
命令 | 描述 |
---|---|
systemctl start name.service | 启动服务 |
systemctl stop name.service | 停止服务 |
systemctl restart name.service | 重启服务(没启动的服务会启动) |
systemctl try-restart name.service | 只重启正在运行的服务 |
systemctl reload name.service | 重载配置文件 |
systemctl status name.service systemctl is-active name.service | 检查服务状态检查服务是否启动 |
systemctl list-units --type service --all | 显示所有的服务状态 |
systemctl enable name.service | 启用开机自启服务 |
systemctl disable name.service | 停用自启服务 |
systemctl status name.service systemctl is-enabled name.service | 检查服务状态查看服务是否自启 |
systemctl list-unit-files --type service | 查看所有服务 |
systemctl list-dependencies --after | 列出在指定服务之前启动的服务(依赖) |
systemctl list-dependencies --before | 列出在指定服务之后启动的服务(被依赖) |
ps
ps命令用于显示当前进程的状态,类似于 windows 的任务管理器
ps [选项]
选项
- -a:列出所有的进程
- -e:列出所有的进程,等同于
-A
- -f:显示不包含资源使用率的相关信息
- ‐H:以进程层级格式显示进程相关信息
- -w:显示加宽可以显示较多的信息
- -u:显示较详细的信息
- -x:显示其他使用者的行程
显示信息的格式说明
列名 | 说明 |
---|---|
USER | 进程拥有者 |
PID | 进程ID |
%CPU | 占用的 CPU 使用率 |
%MEM | 占用的内存使用率 |
VSZ | 占用的虚拟内存大小 |
RSS | 占用的常驻内存大小 |
TTY | 执行的终端编号 |
STAT | 该进程的状态* |
START | 进程开始时间 |
TIME | CPU使用时间 |
COMMAND | 所执行的命令 |
*STAT表示的进程状态有如下几种:
- D: 无法中断的休眠状态 ,将一直等待事件的发生或等待某种系统资源
- R: 正在执行中
- S: 可中断状态
- T: 暂停执行
- Z: 不存在但暂时无法消除,也叫僵尸进程
- 每个进程在运行结束后都会处于僵死状态,等待父进程调用进而释放系统资源,处于该状态的进程已经运行结束,但是它的父进程还没有释放其系统资源
- W: 没有足够的内存可分配
- <: 高优先序的进程
- N: 低优先序的进程
- +:前台进程
- l:多线程进程
- s:主进程(先导进程)
实例
- 常用组合:ps aux
u:以用户为中心组织进程状态信息显示
a:与终端相关的进程;
x:与终端无关的进程;
[root@localhost ~]# ps aux | head -n 5
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.3 128144 6656 ? Ss 5月10 0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0.0 0.0 0 0 ? S 5月10 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 5月10 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S< 5月10 0:00 [kworker/0:0H]
- 常用组合:ps -ef
-e:显示所有进程
-f:显示完整格式程序信息
[root@localhost ~]# ps -ef |head -n 10
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 5月10 ? 00:00:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0 0 5月10 ? 00:00:00 [kthreadd]
root 3 2 0 5月10 ? 00:00:00 [ksoftirqd/0]
root 5 2 0 5月10 ? 00:00:00 [kworker/0:0H]
root 6 2 0 5月10 ? 00:00:00 [kworker/u256:0]
root 7 2 0 5月10 ? 00:00:00 [migration/0]
root 8 2 0 5月10 ? 00:00:00 [rcu_bh]
root 9 2 0 5月10 ? 00:00:01 [rcu_sched]
root 10 2 0 5月10 ? 00:00:00 [lru-add-drain]
- 常用组合:ps -efH
查看进程以层级格式(类似于pstree命令)
[root@localhost ~]# ps -efH
root 1 0 0 14:26 ? 00:00:00 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 479 1 0 14:26 ? 00:00:00 /usr/lib/systemd/systemd-journald
root 500 1 0 14:26 ? 00:00:00 /usr/sbin/lvmetad -f
root 507 1 0 14:26 ? 00:00:00 /usr/lib/systemd/systemd-udevd
root 615 1 0 14:27 ? 00:00:00 /sbin/auditd
polkitd 638 1 0 14:27 ? 00:00:00 /usr/lib/polkit-1/polkitd --no-debug
dbus 639 1 0 14:27 ? 00:00:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
root 646 1 0 14:27 ? 00:00:00 /usr/sbin/NetworkManager --no-daemon
root 649 1 0 14:27 ? 00:00:00 /usr/sbin/irqbalance --foreground
root 653 1 0 14:27 ? 00:00:00 /usr/lib/systemd/systemd-logind
root 655 1 0 14:27 ? 00:00:00 /usr/sbin/crond -n
chrony 661 1 0 14:27 ? 00:00:00 /usr/sbin/chronyd
root 662 1 0 14:27 ? 00:00:00 login -- root
- 按照CPU使用率排序查看所有进程
[root@localhost ~]# ps aux --sort %cpu # 递增
[root@localhost ~]# ps aux --sort -%cpu # 递减
- 按照实际内存使用排序查看所有进程
[root@localhost ~]# ps aux --sort rss # 递增
[root@localhost ~]# ps aux --sort -rss # 递减
- 按照父子进程显示ssh服务的层级关系
[root@localhost ~]# ps auxf |grep sshd
# ps -efH
root 6814 0.0 0.2 112756 4320 ? Ss 09:06 0:00 /usr/sbin/sshd -D
root 7097 0.0 0.2 158760 5576 ? Ss 09:06 0:00 \_ sshd: root@pts/0
root 7337 0.1 0.2 158760 5588 ? Ss 10:21 0:00 \_ sshd: root@pts/1
root 7364 0.0 0.0 112724 988 pts/1 S+ 10:24 0:00 \_ grep --color=auto sshd
- 自定义显示格式
[root@localhost ~]# ps -axo user,pid,ppid,%mem,%cpu,command --sort -%cpu
- 查看指定进程的PID,多种查看的方式
[root@localhost ~]# cat /run/sshd.pid
[root@localhost ~]# ps aux |grep sshd
[root@localhost ~]# pgrep -l sshd
[root@localhost ~]# pidof sshd
- 查看进程树
[root@localhost ~]# yum install -y psmisc
[root@localhost ~]# pstree
[root@localhost ~]# pstree --help
top
top命令用于实时显示 process 的动态
top [选项]
[root@localhost ~]# top
[root@localhost ~]# top -d 1 # 一秒钟刷新一次
[root@localhost ~]# top -d 1 -p 6995 # 查看指定PID
[root@localhost ~]# top -d 1 -p 6995,1 # 查看多个PID进程
[root@localhost ~]# top -d 1 -u apache # 查看指定用户的进程
[root@localhost ~]# top -d 1 -b -n 2 > top.txt # 将2次top信息写入到文件
第1行:系统时间、运行时间、登录终端数、系统负载(三个数值分别为1分钟、5分钟、15分钟内的平 均值,数值越小意味着负载越低)。
第2行:进程总数、运行中的进程数、睡眠中的进程数、停止的进程数、僵死的进程数。
第3行:用户占用资源百分比、系统内核占用资源百分比、改变过优先级的进程资源百分比、空闲的资源 百分比等。
第4行:物理内存总量、内存使用量、内存空闲量、作为内核缓存的内存量。(buffer和cache之间的区 别,cache是提高cpu和内存之间的数据交换速度,buffer是io设备和存储设备之间的缓冲区)
第5行:虚拟内存总量、虚拟内存使用量、虚拟内存空闲量、已被提前加载的内存量。
选项
- -d: 改变显示的更新速度,或是在交互式指令列( interactive command)按 s
- -c: 切换显示模式,共有两种模式,一是只显示程序的名称,另一种是显示完整的路径与名称
- -S: 累积模式,会将己完成或消失的子行程 ( dead child process ) 的 CPU time 累积起来
- -s: 安全模式,将交互式指令取消, 避免潜在的危机
- -i: 不显示任何闲置 (idle) 或无用 (zombie) 的行程
- -n: 更新的次数,完成后将会退出 top
- -b: 显示模式,搭配 "n" 参数一起使用,可以用来将 top 的结果输出到文件内
- -z:彩色
交互模式快捷键
快捷键 | 功能 |
---|---|
空格 | 立即刷新 |
P | 根据CPU使用多少排序 |
T | 根据时间、累计排序 |
q | 退出top命令 |
m | 切换显示内存信息 |
t | 切换显示进程和CPU状态信息 |
c | 切换显示命令名称和完整命令行 |
M | 根据内存的大小排序 |
W | 将当前设置写入 ~/.toprc 文件中,这是top配置文件推荐方法 |
N | 以PID的大小排序 |
z | 彩色 |
实例
- 显示进程信息,每个1秒钟刷新一次
[root@localhost ~]# top -d 1
- 显示完整命令
[root@localhost ~]# top -c
- 更新两次后终止更新显示
[root@localhost ~]# top -n 2
- 显示指定的进程信息
[root@localhost ~]# top -p 7097
kill
kill 命令用于删除执行中的程序或工作
kill 可将指定的信号送至程序。预设的信号为 SIGTERM(15),可将指定程序终止
kill [-s <信息名称或编号>][程序] 或 kill [-l <信息编号>]
选项
- -l <信号编号>: 若不加<信号编号>选项,则 -l 参数会列出全部的信号名称
- -s <信号名称或编号>:指定要送出的信息
- [程序]:[程序]可以是程序的PID或是PGID
使用 kill -l 命令列出所有可用信号,最常用的信号如下
编号 | 信号名 | 作用 |
---|---|---|
1 | SIGHUP | 重新加载配置 |
2 | SIGINT | 键盘中断^C |
3 | SIGQUIT | 键盘退出 |
9 | SIGKILL | 强制终止 |
15 | SIGTERM | 终止(正常结束),缺省信号 |
18 | SIGCONT | 继续 |
19 | SIGSTOP | 停止 |
20 | SIGTSTP | 暂停^Z |
实例
- 杀死所有的ping命令,在linux命令中,使用反引号`包含的命令会优先执行,并将执行的结果作为参数提供给命令。
[root@localhost ~]# kill `pgrep ping`
- 强制杀死进程
[root@localhost ~]# kill -9 `pgrep ping`
- 温柔的杀死进程
[root@localhost ~]# kill -15 `pgrep ping`
- 重新加载配置
[root@localhost ~]# kill -HUP pid
[root@localhost ~]# kill -1 pid
pkill
pkill 用于杀死一个进程,与 kill 不同的是它会杀死指定名字的所有进程,类似于 killall 命令
pkill [选项] name
选项
- name: 进程名
- -u:指定用户名
- -t:指定终端
实例
- 结束所有的sshd进程
[root@localhost ~]# pkill sshd
- 结束用户user1的所有进程
[root@localhost ~]# pkill -u user1
- 终止pts/2上所有进程
[root@localhost ~]# pkill -t pts/2
- 终止pts/2上所有进程,并结束pts/2
[root@localhost ~]# pkill -9 -t pts/2
- 查看远程登录用户,并踢出用户
[root@localhost ~]# w
15:02:26 up 5:21, 2 users, load average: 0.05, 0.03, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty1 14:41 20:34 0.02s 0.02s -bash
root pts/0 192.168.175.1 14:42 2.00s 0.05s 0.01s w
user1 pts/1 192.168.175.1 14:40 20:34 0.02s 0.02s -bash
[root@localhost ~]# pkill -u user1
进程优先级 nice
Linux进程调度及多任务
每个CPU(或CPU核心)在一个时间点上只能处理一个进程,通过时间片技术,Linux实际能够运行的进程 (和线程数)可以超出实际可用的CPU及核心数量。Linux内核进程调度程序将多个进程在CPU核心上快速 切换,从而给用户多个进程在同时运行的假象。(并发)
相对优先级
由于不是每个进程都与其他进程同样重要,可告知进程调度程序为不同的进程使用不同的调度策略。常规系统上运行的大多数进程所使用的的调度策略为SCHED_OTHER(也称为SCHED_NORMAL),但还有其他 一些调度策略用于不同的目的。SCHED_OTHER调度策略运行的进程的相对优先级称为进程的nice值, 可以有40种不同级别的nice值。
进程优先级 0-99:实时优先级,数字越小,优先级越低
00-139:静态优先级,数字越小,优先级越高
进程默认启动时nice为0,优先级为120
nice值越高表示优先级越低,例如+19,该进程容易将CPU使用量让给其他进程
nice值越低表示优先级越高,例如-20,该进程更倾向于不让出CPU
查看进程的nice级别
使用ps查看
[root@localhost ~]# ps axo pid,command,nice --sort=nice
[root@localhost ~]# ps axo pid,command,nice,cls --sort=-nice
TS表示该进程使用的调度策略为SCHED_OTHER
使用top查看
NI:实际nice级别
PR:将nice级别显示为映射到更大优先级队列,-20映射到0,+19映射到39
启动具有不同nice级别的进程
启动进程的时候为进程指定nice值
启动进程时,通常会继承父进程的nice级别,默认为0
[root@localhost ~]# nice -n -20 vim
[root@localhost ~]# ps axo command,pid,nice |grep vim
PRI
在top命令中可以看到有PR这个数值,PR 和 nice 值,都会影响进程执行的优先级。PR 由 OS 内核动态调整,用户不能调整(PR 值越低,进程执行的优先级越高)。
nice值用户可以自己调整,在用户调整了nice值后系统会通过如下公式来调整新的PR值,从而确定这个进程在系统中的优先级
PR(新) = PR(旧) + nice
PR值是OS动态调整的,但是PR的最终值还是需要由OS分析决定的
更改现有进程的nice级别
- 使用top更改nice级别
r 调整进程的优先级(Nice Level) (-20高) - - - 0 - - - (19低)
- 使用shell更改nice级别
[root@localhost ~]# sleep 7000 &
[2] 10267
[root@localhost ~]# renice -20 10267
10267 (进程 ID) 旧优先级为 0,新优先级为 -20
jobs
jobs 命令可以用来查看当前终端放入后台的任务
jobs [-lnprs] [任务声明 ...]
将任务放入到后台
Linux 命令放入后台的方法有两种:
- 在命令后面加入
空格 &
。使用这种方法放入后台的命令,在后台处于执行状态 - 命令执行过裎中按 Ctrl+Z 快捷键,命令在后台处于暂停状态
实例
- 将任务放入后台,然后查看任务
- "+"号代表最近一个放入后台的工作,也是工作恢复时默认恢复的工作
- "-"号代表倒数第二个放入后台的工作
[root@localhost ~]# top &
[root@localhost ~]# vi &
[root@localhost ~]# ping baidu.com > /dev/null &
# 让ping运行,但是不显示结果
[root@localhost ~]# jobs
[1] 已停止 top
[2]- 已停止 vi
[3]+ 运行中 ping baidu.com > /dev/null &
将任务恢复到前台
fg 命令用于把后台工作恢复到前台执行
fg %工作号
注意,在使用此命令时,% 可以省略,但若将% 工作号全部省略,则此命令会将带有 + 号的工作恢复到前台。另外,使用此命令的过程中, % 可有可无。
实例
- 将top恢复到前台
- 命令虽然是对的,但是top这种需要交互的任务是无法后台的,所以也恢复不了
[root@localhost ~]# top &
[1] 20584
[root@localhost ~]# jobs
[1]+ 已停止 top
[root@localhost ~]# fg 1
后台任务恢复到后台运行
前面讲过,使用Ctrl+z
快捷键的方式,可以将前台工作放入后台,但是会处于暂停状态,可以使用bg命令
bg %工作号
这里的 % 可以省略
实例
- 将ping命令暂停到后台,然后恢复后台运行
[root@localhost ~]# ping baidu.com > /dev/null
^Z # 这边按下了Ctrl+z
[1]+ 已停止 ping baidu.com > /dev/null
[root@localhost ~]# jobs
[1]+ 已停止 ping baidu.com > /dev/null
[root@localhost ~]# bg %1
[1]+ ping baidu.com > /dev/null &
[root@localhost ~]# jobs
[1]+ 运行中 ping baidu.com > /dev/null &
nohup
虽然可以将程序放在后台运行,但是一旦关闭远程连接那么程序就会中断,如果我们想要将程序一直保持在后台运行,那么我们可以有如下三个选择:
- 把需要在后台执行的命令加入
/etc/rc.local
文件,让系统在启动时执行这个后台程序。这种方法的问题是,服务器是不能随便重启的,如果有临时后台任务,就不能执行了 - 使用系统定时任务,让系统在指定的时间执行某个后台命令。这样放入后台的命令与终端无关,是不依赖登录终端的
- 使用 nohup 命令
nohup 命令&
注意,这里的‘&’表示此命令会在终端后台工作;反之d,如果没有‘&’,则表示此命令会在终端前台工作。
实例
- 让一个任务后台运行
[root@localhost ~]# nohup ping baidu.com &
我们退出远程连接,然后重新登录回来,会看到ping baidu.com
依旧在运行,查看~/nohup.out
文件可以看到程序执行输出的内容
[root@localhost ~]# ps aux |grep ping
root 7157 0.0 0.0 149968 1988 ? S 14:12 0:00 ping baidu.com
[root@localhost ~]# tail -f nohup.out